vagrant-bosh 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.gitmodules +6 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +20 -0
  6. data/README.md +73 -0
  7. data/Rakefile +2 -0
  8. data/dev/.gitignore +1 -0
  9. data/dev/Vagrantfile +30 -0
  10. data/dev/example-bosh-manifest.yml +188 -0
  11. data/dev/example-winston-manifest.yml +70 -0
  12. data/go/.gitignore +11 -0
  13. data/go/bin/build +10 -0
  14. data/go/bin/build-linux-amd64 +9 -0
  15. data/go/bin/env +13 -0
  16. data/go/bin/go +5 -0
  17. data/go/bin/golint +19 -0
  18. data/go/bin/test +37 -0
  19. data/go/src/boshprovisioner/agent/client/client_interface.go +73 -0
  20. data/go/src/boshprovisioner/agent/client/fakes/fake_client.go +81 -0
  21. data/go/src/boshprovisioner/agent/client/http_client.go +299 -0
  22. data/go/src/boshprovisioner/agent/client/http_client_envelope.go +107 -0
  23. data/go/src/boshprovisioner/deployment/deployment.go +221 -0
  24. data/go/src/boshprovisioner/deployment/instance.go +54 -0
  25. data/go/src/boshprovisioner/deployment/manifest/deployment.go +80 -0
  26. data/go/src/boshprovisioner/deployment/manifest/ips.go +23 -0
  27. data/go/src/boshprovisioner/deployment/manifest/manifest.go +143 -0
  28. data/go/src/boshprovisioner/deployment/manifest/manifest_suite_test.go +13 -0
  29. data/go/src/boshprovisioner/deployment/manifest/manifest_test.go +86 -0
  30. data/go/src/boshprovisioner/deployment/manifest/syntax_validator.go +186 -0
  31. data/go/src/boshprovisioner/deployment/manifest/watch_time.go +47 -0
  32. data/go/src/boshprovisioner/deployment/manifest_reader.go +46 -0
  33. data/go/src/boshprovisioner/deployment/reader_factory.go +25 -0
  34. data/go/src/boshprovisioner/deployment/semantic_validator.go +111 -0
  35. data/go/src/boshprovisioner/downloader/blobstore_downloader.go +55 -0
  36. data/go/src/boshprovisioner/downloader/default_mux_downloader.go +22 -0
  37. data/go/src/boshprovisioner/downloader/downloader_interface.go +6 -0
  38. data/go/src/boshprovisioner/downloader/http_downloader.go +53 -0
  39. data/go/src/boshprovisioner/downloader/local_fs_downloader.go +48 -0
  40. data/go/src/boshprovisioner/downloader/mux_downloader.go +69 -0
  41. data/go/src/boshprovisioner/eventlog/log.go +72 -0
  42. data/go/src/boshprovisioner/eventlog/stage.go +39 -0
  43. data/go/src/boshprovisioner/eventlog/task.go +58 -0
  44. data/go/src/boshprovisioner/index/file_index.go +289 -0
  45. data/go/src/boshprovisioner/index/file_index_test.go +296 -0
  46. data/go/src/boshprovisioner/index/index_interface.go +18 -0
  47. data/go/src/boshprovisioner/index/index_suite_test.go +13 -0
  48. data/go/src/boshprovisioner/instance/templatescompiler/concrete_templates_compiler.go +273 -0
  49. data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/erb_renderer.go +117 -0
  50. data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/erbrenderer_suite_test.go +13 -0
  51. data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/render_properties.go +77 -0
  52. data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/render_properties_test.go +142 -0
  53. data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/template_evaluation_context.go +85 -0
  54. data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/template_evaluation_context_rb.go +155 -0
  55. data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/concrete_jobs_repository.go +64 -0
  56. data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/concrete_runtime_packages_repository.go +105 -0
  57. data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/concrete_template_to_job_repository.go +76 -0
  58. data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/jobs_repository_interface.go +31 -0
  59. data/go/src/boshprovisioner/instance/templatescompiler/rendered_archives_compiler.go +81 -0
  60. data/go/src/boshprovisioner/instance/templatescompiler/templates_compiler_interface.go +20 -0
  61. data/go/src/boshprovisioner/instance/templatescompiler/templatesrepo/ct_repository.go +54 -0
  62. data/go/src/boshprovisioner/instance/templatescompiler/templatesrepo/templates_repository_interface.go +16 -0
  63. data/go/src/boshprovisioner/instance/updater/applier/applier.go +93 -0
  64. data/go/src/boshprovisioner/instance/updater/applier/empty_state.go +66 -0
  65. data/go/src/boshprovisioner/instance/updater/applier/job_state.go +178 -0
  66. data/go/src/boshprovisioner/instance/updater/drainer.go +72 -0
  67. data/go/src/boshprovisioner/instance/updater/preparer.go +39 -0
  68. data/go/src/boshprovisioner/instance/updater/starter.go +36 -0
  69. data/go/src/boshprovisioner/instance/updater/stopper.go +36 -0
  70. data/go/src/boshprovisioner/instance/updater/updater.go +102 -0
  71. data/go/src/boshprovisioner/instance/updater/updater_factory.go +83 -0
  72. data/go/src/boshprovisioner/instance/updater/updater_suite_test.go +13 -0
  73. data/go/src/boshprovisioner/instance/updater/waiter.go +77 -0
  74. data/go/src/boshprovisioner/instance/updater/waiter_test.go +103 -0
  75. data/go/src/boshprovisioner/main/config.go +77 -0
  76. data/go/src/boshprovisioner/main/main.go +183 -0
  77. data/go/src/boshprovisioner/main/repos_factory.go +96 -0
  78. data/go/src/boshprovisioner/packagescompiler/compiledpackagesrepo/compiled_packages_repository_interface.go +17 -0
  79. data/go/src/boshprovisioner/packagescompiler/compiledpackagesrepo/concrete_compiled_packages_repository.go +61 -0
  80. data/go/src/boshprovisioner/packagescompiler/concrete_packages_compiler.go +179 -0
  81. data/go/src/boshprovisioner/packagescompiler/concrete_packages_compiler_factory.go +48 -0
  82. data/go/src/boshprovisioner/packagescompiler/packages_compiler_interface.go +20 -0
  83. data/go/src/boshprovisioner/packagescompiler/packagesrepo/concrete_packages_repository.go +65 -0
  84. data/go/src/boshprovisioner/packagescompiler/packagesrepo/packages_repository_interface.go +16 -0
  85. data/go/src/boshprovisioner/provisioner/blobstore_config.go +65 -0
  86. data/go/src/boshprovisioner/provisioner/blobstore_provisioner.go +38 -0
  87. data/go/src/boshprovisioner/provisioner/deployment_provisioner.go +97 -0
  88. data/go/src/boshprovisioner/provisioner/instance_provisioner.go +48 -0
  89. data/go/src/boshprovisioner/provisioner/release_compiler.go +133 -0
  90. data/go/src/boshprovisioner/release/job/job.go +86 -0
  91. data/go/src/boshprovisioner/release/job/manifest/manifest.go +79 -0
  92. data/go/src/boshprovisioner/release/job/manifest/manifest_suite_test.go +13 -0
  93. data/go/src/boshprovisioner/release/job/manifest/manifest_test.go +42 -0
  94. data/go/src/boshprovisioner/release/job/manifest/syntax_validator.go +43 -0
  95. data/go/src/boshprovisioner/release/job/reader_factory.go +34 -0
  96. data/go/src/boshprovisioner/release/job/tar_reader.go +133 -0
  97. data/go/src/boshprovisioner/release/manifest/manifest.go +96 -0
  98. data/go/src/boshprovisioner/release/manifest_reader.go +29 -0
  99. data/go/src/boshprovisioner/release/reader_factory.go +34 -0
  100. data/go/src/boshprovisioner/release/release.go +144 -0
  101. data/go/src/boshprovisioner/release/release_suite_test.go +13 -0
  102. data/go/src/boshprovisioner/release/release_test.go +129 -0
  103. data/go/src/boshprovisioner/release/tar_reader.go +139 -0
  104. data/go/src/boshprovisioner/releasesrepo/blobstore_releases_repository.go +114 -0
  105. data/go/src/boshprovisioner/releasesrepo/releases_repository_interface.go +15 -0
  106. data/go/src/boshprovisioner/tar/cmd_compressor.go +68 -0
  107. data/go/src/boshprovisioner/tar/cmd_extractor.go +47 -0
  108. data/go/src/boshprovisioner/tar/compressor_interface.go +6 -0
  109. data/go/src/boshprovisioner/tar/extractor_interface.go +6 -0
  110. data/go/src/boshprovisioner/util/string_keyed.go +70 -0
  111. data/go/src/boshprovisioner/vm/agent_provisioner.go +266 -0
  112. data/go/src/boshprovisioner/vm/asset_manager.go +61 -0
  113. data/go/src/boshprovisioner/vm/deps_provisioner.go +92 -0
  114. data/go/src/boshprovisioner/vm/monit_provisioner.go +83 -0
  115. data/go/src/boshprovisioner/vm/runit_provisioner.go +225 -0
  116. data/go/src/boshprovisioner/vm/simple_cmds.go +54 -0
  117. data/go/src/boshprovisioner/vm/vcap_user_provisioner.go +120 -0
  118. data/go/src/boshprovisioner/vm/vm.go +19 -0
  119. data/go/src/boshprovisioner/vm/vm_provisioner.go +57 -0
  120. data/go/src/boshprovisioner/vm/vm_provisioner_factory.go +97 -0
  121. data/lib/vagrant-bosh/asset_uploader.rb +53 -0
  122. data/lib/vagrant-bosh/assets/agent/agent-log +5 -0
  123. data/lib/vagrant-bosh/assets/agent/agent-run +12 -0
  124. data/lib/vagrant-bosh/assets/agent/agent.cert +18 -0
  125. data/lib/vagrant-bosh/assets/agent/agent.json +9 -0
  126. data/lib/vagrant-bosh/assets/agent/agent.key +27 -0
  127. data/lib/vagrant-bosh/assets/agent/bosh-agent +0 -0
  128. data/lib/vagrant-bosh/assets/agent/bosh-agent-rc +18 -0
  129. data/lib/vagrant-bosh/assets/agent/bosh-blobstore-dav +0 -0
  130. data/lib/vagrant-bosh/assets/monit/monit +0 -0
  131. data/lib/vagrant-bosh/assets/monit/monit-log +5 -0
  132. data/lib/vagrant-bosh/assets/monit/monit-run +9 -0
  133. data/lib/vagrant-bosh/assets/monit/monitrc +8 -0
  134. data/lib/vagrant-bosh/assets/provisioner +0 -0
  135. data/lib/vagrant-bosh/bootstrapper.rb +59 -0
  136. data/lib/vagrant-bosh/communicator.rb +50 -0
  137. data/lib/vagrant-bosh/config.rb +15 -0
  138. data/lib/vagrant-bosh/errors.rb +11 -0
  139. data/lib/vagrant-bosh/plugin.rb +25 -0
  140. data/lib/vagrant-bosh/provisioner.rb +46 -0
  141. data/lib/vagrant-bosh/provisioner_tracker.rb +41 -0
  142. data/lib/vagrant-bosh/ui.rb +77 -0
  143. data/lib/vagrant-bosh/version.rb +5 -0
  144. data/lib/vagrant-bosh.rb +15 -0
  145. data/templates/locales/en.yml +15 -0
  146. data/vagrant-bosh.gemspec +20 -0
  147. metadata +191 -0
@@ -0,0 +1,80 @@
1
+ package manifest
2
+
3
+ import (
4
+ "encoding/json"
5
+
6
+ bosherr "bosh/errors"
7
+ )
8
+
9
+ func (d Deployment) InstanceWatchTime(job Job, i int) WatchTime {
10
+ var canaries int
11
+
12
+ if job.Update.Canaries != nil {
13
+ canaries = *job.Update.Canaries
14
+ } else if d.Update.Canaries != nil {
15
+ canaries = *d.Update.Canaries
16
+ }
17
+
18
+ if canaries > i {
19
+ return d.CanaryWatchTime(job)
20
+ }
21
+
22
+ return d.CanaryWatchTime(job)
23
+ }
24
+
25
+ func (d Deployment) CanaryWatchTime(job Job) WatchTime {
26
+ if job.Update.CanaryWatchTime != nil {
27
+ return *job.Update.CanaryWatchTime
28
+ } else if d.Update.CanaryWatchTime != nil {
29
+ return *d.Update.CanaryWatchTime
30
+ }
31
+
32
+ return DefaultWatchTime
33
+ }
34
+
35
+ func (d Deployment) UpdateWatchTime(job Job) WatchTime {
36
+ if job.Update.UpdateWatchTime != nil {
37
+ return *job.Update.UpdateWatchTime
38
+ } else if d.Update.UpdateWatchTime != nil {
39
+ return *d.Update.UpdateWatchTime
40
+ }
41
+
42
+ return DefaultWatchTime
43
+ }
44
+
45
+ func (d Deployment) InstanceProperties(job Job, i int) Properties {
46
+ result, err := job.deepCopyProperties()
47
+ if err != nil {
48
+ panic("Deep copying job properties")
49
+ }
50
+
51
+ for name, value := range d.Properties {
52
+ if _, ok := result[name]; !ok {
53
+ result[name] = value
54
+ }
55
+ }
56
+
57
+ return result
58
+ }
59
+
60
+ // deepCopyJobProperties makes a deep copy of job properties.
61
+ // Always returns an initialized map even if job properties are nil.
62
+ func (j Job) deepCopyProperties() (Properties, error) {
63
+ result := map[string]interface{}{}
64
+
65
+ if j.Properties == nil {
66
+ return result, nil
67
+ }
68
+
69
+ bytes, err := json.Marshal(j.Properties)
70
+ if err != nil {
71
+ return result, bosherr.WrapError(err, "Marshalling job properties")
72
+ }
73
+
74
+ err = json.Unmarshal(bytes, &result)
75
+ if err != nil {
76
+ return result, bosherr.WrapError(err, "Unmarshalling job properties")
77
+ }
78
+
79
+ return result, nil
80
+ }
@@ -0,0 +1,23 @@
1
+ package manifest
2
+
3
+ import (
4
+ gonet "net"
5
+ "strings"
6
+
7
+ bosherr "bosh/errors"
8
+ )
9
+
10
+ func NewIPsFromStrings(strs []string) ([]gonet.IP, error) {
11
+ var ips []gonet.IP
12
+
13
+ for _, str := range strs {
14
+ ip := gonet.ParseIP(strings.Trim(str, " "))
15
+ if ip == nil {
16
+ return ips, bosherr.New("Parsing IP %s", str)
17
+ }
18
+
19
+ ips = append(ips, ip)
20
+ }
21
+
22
+ return ips, nil
23
+ }
@@ -0,0 +1,143 @@
1
+ // Package manifest represents structure
2
+ // of a user entered YAML deployment manifest.
3
+ package manifest
4
+
5
+ import (
6
+ gonet "net"
7
+
8
+ bosherr "bosh/errors"
9
+ boshsys "bosh/system"
10
+ "github.com/fraenkel/candiedyaml"
11
+ )
12
+
13
+ type Manifest struct {
14
+ Deployment Deployment
15
+ }
16
+
17
+ type Deployment struct {
18
+ Name string `yaml:"name"`
19
+
20
+ Releases []Release `yaml:"releases"`
21
+
22
+ Networks []Network `yaml:"networks"`
23
+
24
+ Compilation Compilation `yaml:"compilation"`
25
+
26
+ // Deployment-wide update config can be
27
+ // overwritten by job-specific update config
28
+ Update Update `yaml:"update"`
29
+
30
+ Jobs []Job `yaml:"jobs"`
31
+
32
+ // Global properties.
33
+ // Non-raw field is populated by the validator.
34
+ PropertiesRaw map[interface{}]interface{} `yaml:"properties"`
35
+ Properties Properties
36
+ }
37
+
38
+ type Release struct {
39
+ Name string `yaml:"name"`
40
+ Version string `yaml:"version"`
41
+
42
+ // Not offical BOSH manifest construct
43
+ URL string `yaml:"url"`
44
+ }
45
+
46
+ const (
47
+ NetworkTypeManual = "manual"
48
+ NetworkTypeDynamic = "dynamic"
49
+ NetworkTypeVip = "vip"
50
+ )
51
+
52
+ var NetworkTypes = []string{NetworkTypeManual, NetworkTypeDynamic, NetworkTypeVip}
53
+
54
+ type Network struct {
55
+ Name string `yaml:"name"`
56
+
57
+ // e.g. manual, dynamic, vip
58
+ Type string `yaml:"type"`
59
+ }
60
+
61
+ type Compilation struct {
62
+ NetworkName string `yaml:"network"`
63
+ }
64
+
65
+ type Job struct {
66
+ Name string `yaml:"name"`
67
+ Instances int `yaml:"instances"`
68
+
69
+ Update Update `yaml:"update"`
70
+
71
+ // Deprecated in favor of Templates
72
+ Template interface{} `yaml:"template"`
73
+
74
+ Templates []Template `yaml:"templates"`
75
+
76
+ // Job specific properties that override global properties.
77
+ // Non-raw field is populated by the validator.
78
+ PropertiesRaw map[interface{}]interface{} `yaml:"properties"`
79
+ Properties Properties
80
+
81
+ NetworkAssociations []NetworkAssociation `yaml:"networks"`
82
+ }
83
+
84
+ type Template struct {
85
+ Name string `yaml:"name"`
86
+ ReleaseName string `yaml:"release"`
87
+ }
88
+
89
+ type Properties map[string]interface{}
90
+
91
+ type Update struct {
92
+ // Integer pointers to determine absence
93
+ Canaries *int `yaml:"canaries"`
94
+ MaxInFlight *int `yaml:"max_in_flight"`
95
+
96
+ // String pointers to determine absence
97
+ CanaryWatchTimeRaw *string `yaml:"canary_watch_time"`
98
+ UpdateWatchTimeRaw *string `yaml:"update_watch_time"`
99
+
100
+ // Populated by the validator
101
+ CanaryWatchTime *WatchTime
102
+ UpdateWatchTime *WatchTime
103
+ }
104
+
105
+ type NetworkAssociation struct {
106
+ NetworkName string `yaml:"name"`
107
+
108
+ // Non-raw field populated by the validator.
109
+ StaticIPsRaw []string `yaml:"static_ips"`
110
+ StaticIPs []gonet.IP
111
+ }
112
+
113
+ // NewManifestFromPath returns manifest read from the file system.
114
+ // Before returning manifest is syntactically validated.
115
+ func NewManifestFromPath(path string, fs boshsys.FileSystem) (Manifest, error) {
116
+ bytes, err := fs.ReadFile(path)
117
+ if err != nil {
118
+ return Manifest{}, bosherr.WrapError(err, "Reading manifest %s", path)
119
+ }
120
+
121
+ return NewManifestFromBytes(bytes)
122
+ }
123
+
124
+ // NewManifestFromBytes returns manifest built from given bytes.
125
+ // Before returning manifest is syntactically validated.
126
+ func NewManifestFromBytes(bytes []byte) (Manifest, error) {
127
+ var manifest Manifest
128
+ var deployment Deployment
129
+
130
+ err := candiedyaml.Unmarshal(bytes, &deployment)
131
+ if err != nil {
132
+ return manifest, bosherr.WrapError(err, "Parsing deployment")
133
+ }
134
+
135
+ manifest.Deployment = deployment
136
+
137
+ err = NewSyntaxValidator(&manifest).Validate()
138
+ if err != nil {
139
+ return manifest, bosherr.WrapError(err, "Validating manifest syntactically")
140
+ }
141
+
142
+ return manifest, nil
143
+ }
@@ -0,0 +1,13 @@
1
+ package manifest_test
2
+
3
+ import (
4
+ . "github.com/onsi/ginkgo"
5
+ . "github.com/onsi/gomega"
6
+
7
+ "testing"
8
+ )
9
+
10
+ func TestManifest(t *testing.T) {
11
+ RegisterFailHandler(Fail)
12
+ RunSpecs(t, "Manifest Suite")
13
+ }
@@ -0,0 +1,86 @@
1
+ package manifest_test
2
+
3
+ import (
4
+ . "github.com/onsi/ginkgo"
5
+ . "github.com/onsi/gomega"
6
+
7
+ . "boshprovisioner/deployment/manifest"
8
+ )
9
+
10
+ var _ = Describe("Manifest", func() {
11
+ Describe("NewManifestFromBytes", func() {
12
+ It("returns manifest with deployment properties that have string keys", func() {
13
+ manifestBytes := []byte(`
14
+ name: fake-deployment
15
+
16
+ networks:
17
+ - name: net1
18
+ type: dynamic
19
+
20
+ compilation:
21
+ network: net1
22
+
23
+ properties:
24
+ prop:
25
+ nest-prop: instance-val
26
+ props:
27
+ - name: nest-prop
28
+ `)
29
+
30
+ manifest, err := NewManifestFromBytes(manifestBytes)
31
+ Expect(err).ToNot(HaveOccurred())
32
+
33
+ depProps := manifest.Deployment.Properties
34
+
35
+ // candiedyaml unmarshals manifest to map[interface{}]interface{}
36
+ // (encoding/json unmarshals manifest to map[string]interface{})
37
+ Expect(depProps).To(Equal(Properties(
38
+ map[string]interface{}{
39
+ "prop": map[string]interface{}{
40
+ "nest-prop": "instance-val",
41
+ },
42
+ "props": []interface{}{
43
+ map[string]interface{}{"name": "nest-prop"},
44
+ },
45
+ },
46
+ )))
47
+ })
48
+
49
+ It("returns manifest with job properties that have string keys", func() {
50
+ manifestBytes := []byte(`
51
+ name: fake-deployment
52
+
53
+ networks:
54
+ - name: net1
55
+ type: dynamic
56
+
57
+ compilation:
58
+ network: net1
59
+
60
+ jobs:
61
+ - name: job-1
62
+ properties:
63
+ prop:
64
+ nest-prop: instance-val
65
+ props:
66
+ - name: nest-prop
67
+ `)
68
+
69
+ manifest, err := NewManifestFromBytes(manifestBytes)
70
+ Expect(err).ToNot(HaveOccurred())
71
+
72
+ jobProps := manifest.Deployment.Jobs[0].Properties
73
+
74
+ Expect(jobProps).To(Equal(Properties(
75
+ map[string]interface{}{
76
+ "prop": map[string]interface{}{
77
+ "nest-prop": "instance-val",
78
+ },
79
+ "props": []interface{}{
80
+ map[string]interface{}{"name": "nest-prop"},
81
+ },
82
+ },
83
+ )))
84
+ })
85
+ })
86
+ })
@@ -0,0 +1,186 @@
1
+ package manifest
2
+
3
+ import (
4
+ bosherr "bosh/errors"
5
+
6
+ bputil "boshprovisioner/util"
7
+ )
8
+
9
+ // SyntaxValidator parses and saves all manifest values to determine
10
+ // their syntactic validity. Determining if individual values make sense
11
+ // in a greater context (within a deployment or a job) is outside of scope.
12
+ // e.g. - can watch time string value be parsed into a time range?
13
+ type SyntaxValidator struct {
14
+ deployment *Deployment
15
+ }
16
+
17
+ func NewSyntaxValidator(manifest *Manifest) SyntaxValidator {
18
+ if manifest == nil {
19
+ panic("Expected manifest to not be nil")
20
+ }
21
+
22
+ return SyntaxValidator{deployment: &manifest.Deployment}
23
+ }
24
+
25
+ func (v SyntaxValidator) Validate() error {
26
+ if v.deployment.Name == "" {
27
+ return bosherr.New("Missing deployment name")
28
+ }
29
+
30
+ err := v.validateUpdate(&v.deployment.Update)
31
+ if err != nil {
32
+ return bosherr.WrapError(err, "Deployment update")
33
+ }
34
+
35
+ for i, net := range v.deployment.Networks {
36
+ err := v.validateNetwork(&v.deployment.Networks[i])
37
+ if err != nil {
38
+ return bosherr.WrapError(err, "Network %s (%d)", net.Name, i)
39
+ }
40
+ }
41
+
42
+ for i, release := range v.deployment.Releases {
43
+ err := v.validateRelease(&v.deployment.Releases[i])
44
+ if err != nil {
45
+ return bosherr.WrapError(err, "Release %s (%d)", release.Name, i)
46
+ }
47
+ }
48
+
49
+ err = v.validateCompilation(&v.deployment.Compilation)
50
+ if err != nil {
51
+ return bosherr.WrapError(err, "Compilation")
52
+ }
53
+
54
+ for i, job := range v.deployment.Jobs {
55
+ err := v.validateJob(&v.deployment.Jobs[i])
56
+ if err != nil {
57
+ return bosherr.WrapError(err, "Job %s (%d)", job.Name, i)
58
+ }
59
+ }
60
+
61
+ props, err := bputil.NewStringKeyed().ConvertMap(v.deployment.PropertiesRaw)
62
+ if err != nil {
63
+ return bosherr.WrapError(err, "Deployment properties")
64
+ }
65
+
66
+ v.deployment.Properties = props
67
+
68
+ return nil
69
+ }
70
+
71
+ func (v SyntaxValidator) validateNetwork(network *Network) error {
72
+ if network.Name == "" {
73
+ return bosherr.New("Missing network name")
74
+ }
75
+
76
+ return v.validateNetworkType(network.Type)
77
+ }
78
+
79
+ func (v SyntaxValidator) validateNetworkType(networkType string) error {
80
+ if networkType == "" {
81
+ return bosherr.New("Missing network type")
82
+ }
83
+
84
+ for _, t := range NetworkTypes {
85
+ if networkType == t {
86
+ return nil
87
+ }
88
+ }
89
+
90
+ return bosherr.New("Unknown network type %s", networkType)
91
+ }
92
+
93
+ func (v SyntaxValidator) validateRelease(release *Release) error {
94
+ if release.Name == "" {
95
+ return bosherr.New("Missing release name")
96
+ }
97
+
98
+ if release.Version == "" {
99
+ return bosherr.New("Missing release version")
100
+ }
101
+
102
+ if release.URL == "" {
103
+ return bosherr.New("Missing release URL")
104
+ }
105
+
106
+ return nil
107
+ }
108
+
109
+ func (v SyntaxValidator) validateCompilation(compilation *Compilation) error {
110
+ if compilation.NetworkName == "" {
111
+ return bosherr.New("Missing network name")
112
+ }
113
+
114
+ return nil
115
+ }
116
+
117
+ func (v SyntaxValidator) validateJob(job *Job) error {
118
+ if job.Name == "" {
119
+ return bosherr.New("Missing job name")
120
+ }
121
+
122
+ if job.Template != nil {
123
+ return bosherr.New("'template' is deprecated in favor of 'templates'")
124
+ }
125
+
126
+ err := v.validateUpdate(&job.Update)
127
+ if err != nil {
128
+ return bosherr.WrapError(err, "Update")
129
+ }
130
+
131
+ props, err := bputil.NewStringKeyed().ConvertMap(job.PropertiesRaw)
132
+ if err != nil {
133
+ return bosherr.WrapError(err, "Properties")
134
+ }
135
+
136
+ job.Properties = props
137
+
138
+ for i, na := range job.NetworkAssociations {
139
+ err := v.validateNetworkAssociation(&job.NetworkAssociations[i])
140
+ if err != nil {
141
+ return bosherr.WrapError(err, "Network association %s (%d)", na.NetworkName, i)
142
+ }
143
+ }
144
+
145
+ return nil
146
+ }
147
+
148
+ // validateUpdate validates deployment level or job level update section
149
+ func (v SyntaxValidator) validateUpdate(update *Update) error {
150
+ if update.CanaryWatchTimeRaw != nil {
151
+ watchTime, err := NewWatchTimeFromString(*update.CanaryWatchTimeRaw)
152
+ if err != nil {
153
+ return bosherr.WrapError(err, "Canary watch time")
154
+ }
155
+
156
+ update.CanaryWatchTime = &watchTime
157
+ }
158
+
159
+ if update.UpdateWatchTimeRaw != nil {
160
+ watchTime, err := NewWatchTimeFromString(*update.UpdateWatchTimeRaw)
161
+ if err != nil {
162
+ return bosherr.WrapError(err, "Update watch time")
163
+ }
164
+
165
+ update.UpdateWatchTime = &watchTime
166
+ }
167
+
168
+ return nil
169
+ }
170
+
171
+ func (v SyntaxValidator) validateNetworkAssociation(na *NetworkAssociation) error {
172
+ if na.NetworkName == "" {
173
+ return bosherr.New("Missing network name")
174
+ }
175
+
176
+ if na.StaticIPsRaw != nil {
177
+ ips, err := NewIPsFromStrings(na.StaticIPsRaw)
178
+ if err != nil {
179
+ return bosherr.WrapError(err, "Static IPs")
180
+ }
181
+
182
+ na.StaticIPs = ips
183
+ }
184
+
185
+ return nil
186
+ }
@@ -0,0 +1,47 @@
1
+ package manifest
2
+
3
+ import (
4
+ "strconv"
5
+ "strings"
6
+
7
+ bosherr "bosh/errors"
8
+ )
9
+
10
+ type WatchTime [2]int
11
+
12
+ var (
13
+ DefaultWatchTime = WatchTime{0, 0}
14
+ )
15
+
16
+ func NewWatchTimeFromString(str string) (WatchTime, error) {
17
+ var watchTime WatchTime
18
+
19
+ parts := strings.Split(str, "-")
20
+ if len(parts) != 2 {
21
+ return watchTime, bosherr.New("Invalid watch time range %s", str)
22
+ }
23
+
24
+ min, err := strconv.Atoi(strings.Trim(parts[0], " "))
25
+ if err != nil {
26
+ return watchTime, bosherr.WrapError(
27
+ err, "Non-positive number as watch time minimum %s", parts[0])
28
+ }
29
+
30
+ max, err := strconv.Atoi(strings.Trim(parts[1], " "))
31
+ if err != nil {
32
+ return watchTime, bosherr.WrapError(
33
+ err, "Non-positive number as watch time maximum %s", parts[1])
34
+ }
35
+
36
+ if max < min {
37
+ return watchTime, bosherr.New(
38
+ "Watch time must have maximum greater than or equal minimum %s", str)
39
+ }
40
+
41
+ watchTime[0], watchTime[1] = min, max
42
+
43
+ return watchTime, nil
44
+ }
45
+
46
+ func (wt WatchTime) Start() int { return wt[0] }
47
+ func (wt WatchTime) End() int { return wt[1] }
@@ -0,0 +1,46 @@
1
+ package deployment
2
+
3
+ import (
4
+ bosherr "bosh/errors"
5
+ boshlog "bosh/logger"
6
+ boshsys "bosh/system"
7
+
8
+ bpdepman "boshprovisioner/deployment/manifest"
9
+ )
10
+
11
+ type ManifestReader struct {
12
+ path string
13
+ fs boshsys.FileSystem
14
+ logger boshlog.Logger
15
+ }
16
+
17
+ func NewManifestReader(
18
+ path string,
19
+ fs boshsys.FileSystem,
20
+ logger boshlog.Logger,
21
+ ) ManifestReader {
22
+ return ManifestReader{path: path, fs: fs, logger: logger}
23
+ }
24
+
25
+ func (r ManifestReader) Read() (Deployment, error) {
26
+ var deployment Deployment
27
+
28
+ manifest, err := bpdepman.NewManifestFromPath(r.path, r.fs)
29
+ if err != nil {
30
+ return deployment, bosherr.WrapError(err, "Reading manifest")
31
+ }
32
+
33
+ deployment.populateFromManifest(manifest)
34
+
35
+ // todo pass by ref?
36
+ err = NewSemanticValidator(deployment).Validate()
37
+ if err != nil {
38
+ return deployment, bosherr.WrapError(err, "Validating deployment semantically")
39
+ }
40
+
41
+ return deployment, nil
42
+ }
43
+
44
+ func (r ManifestReader) Close() error {
45
+ return nil
46
+ }
@@ -0,0 +1,25 @@
1
+ package deployment
2
+
3
+ import (
4
+ boshlog "bosh/logger"
5
+ boshsys "bosh/system"
6
+ )
7
+
8
+ type ReaderFactory struct {
9
+ fs boshsys.FileSystem
10
+ logger boshlog.Logger
11
+ }
12
+
13
+ func NewReaderFactory(
14
+ fs boshsys.FileSystem,
15
+ logger boshlog.Logger,
16
+ ) ReaderFactory {
17
+ return ReaderFactory{
18
+ fs: fs,
19
+ logger: logger,
20
+ }
21
+ }
22
+
23
+ func (rf ReaderFactory) NewManifestReader(path string) ManifestReader {
24
+ return NewManifestReader(path, rf.fs, rf.logger)
25
+ }