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.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.gitmodules +6 -0
- data/Gemfile +3 -0
- data/LICENSE +20 -0
- data/README.md +73 -0
- data/Rakefile +2 -0
- data/dev/.gitignore +1 -0
- data/dev/Vagrantfile +30 -0
- data/dev/example-bosh-manifest.yml +188 -0
- data/dev/example-winston-manifest.yml +70 -0
- data/go/.gitignore +11 -0
- data/go/bin/build +10 -0
- data/go/bin/build-linux-amd64 +9 -0
- data/go/bin/env +13 -0
- data/go/bin/go +5 -0
- data/go/bin/golint +19 -0
- data/go/bin/test +37 -0
- data/go/src/boshprovisioner/agent/client/client_interface.go +73 -0
- data/go/src/boshprovisioner/agent/client/fakes/fake_client.go +81 -0
- data/go/src/boshprovisioner/agent/client/http_client.go +299 -0
- data/go/src/boshprovisioner/agent/client/http_client_envelope.go +107 -0
- data/go/src/boshprovisioner/deployment/deployment.go +221 -0
- data/go/src/boshprovisioner/deployment/instance.go +54 -0
- data/go/src/boshprovisioner/deployment/manifest/deployment.go +80 -0
- data/go/src/boshprovisioner/deployment/manifest/ips.go +23 -0
- data/go/src/boshprovisioner/deployment/manifest/manifest.go +143 -0
- data/go/src/boshprovisioner/deployment/manifest/manifest_suite_test.go +13 -0
- data/go/src/boshprovisioner/deployment/manifest/manifest_test.go +86 -0
- data/go/src/boshprovisioner/deployment/manifest/syntax_validator.go +186 -0
- data/go/src/boshprovisioner/deployment/manifest/watch_time.go +47 -0
- data/go/src/boshprovisioner/deployment/manifest_reader.go +46 -0
- data/go/src/boshprovisioner/deployment/reader_factory.go +25 -0
- data/go/src/boshprovisioner/deployment/semantic_validator.go +111 -0
- data/go/src/boshprovisioner/downloader/blobstore_downloader.go +55 -0
- data/go/src/boshprovisioner/downloader/default_mux_downloader.go +22 -0
- data/go/src/boshprovisioner/downloader/downloader_interface.go +6 -0
- data/go/src/boshprovisioner/downloader/http_downloader.go +53 -0
- data/go/src/boshprovisioner/downloader/local_fs_downloader.go +48 -0
- data/go/src/boshprovisioner/downloader/mux_downloader.go +69 -0
- data/go/src/boshprovisioner/eventlog/log.go +72 -0
- data/go/src/boshprovisioner/eventlog/stage.go +39 -0
- data/go/src/boshprovisioner/eventlog/task.go +58 -0
- data/go/src/boshprovisioner/index/file_index.go +289 -0
- data/go/src/boshprovisioner/index/file_index_test.go +296 -0
- data/go/src/boshprovisioner/index/index_interface.go +18 -0
- data/go/src/boshprovisioner/index/index_suite_test.go +13 -0
- data/go/src/boshprovisioner/instance/templatescompiler/concrete_templates_compiler.go +273 -0
- data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/erb_renderer.go +117 -0
- data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/erbrenderer_suite_test.go +13 -0
- data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/render_properties.go +77 -0
- data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/render_properties_test.go +142 -0
- data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/template_evaluation_context.go +85 -0
- data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/template_evaluation_context_rb.go +155 -0
- data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/concrete_jobs_repository.go +64 -0
- data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/concrete_runtime_packages_repository.go +105 -0
- data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/concrete_template_to_job_repository.go +76 -0
- data/go/src/boshprovisioner/instance/templatescompiler/jobsrepo/jobs_repository_interface.go +31 -0
- data/go/src/boshprovisioner/instance/templatescompiler/rendered_archives_compiler.go +81 -0
- data/go/src/boshprovisioner/instance/templatescompiler/templates_compiler_interface.go +20 -0
- data/go/src/boshprovisioner/instance/templatescompiler/templatesrepo/ct_repository.go +54 -0
- data/go/src/boshprovisioner/instance/templatescompiler/templatesrepo/templates_repository_interface.go +16 -0
- data/go/src/boshprovisioner/instance/updater/applier/applier.go +93 -0
- data/go/src/boshprovisioner/instance/updater/applier/empty_state.go +66 -0
- data/go/src/boshprovisioner/instance/updater/applier/job_state.go +178 -0
- data/go/src/boshprovisioner/instance/updater/drainer.go +72 -0
- data/go/src/boshprovisioner/instance/updater/preparer.go +39 -0
- data/go/src/boshprovisioner/instance/updater/starter.go +36 -0
- data/go/src/boshprovisioner/instance/updater/stopper.go +36 -0
- data/go/src/boshprovisioner/instance/updater/updater.go +102 -0
- data/go/src/boshprovisioner/instance/updater/updater_factory.go +83 -0
- data/go/src/boshprovisioner/instance/updater/updater_suite_test.go +13 -0
- data/go/src/boshprovisioner/instance/updater/waiter.go +77 -0
- data/go/src/boshprovisioner/instance/updater/waiter_test.go +103 -0
- data/go/src/boshprovisioner/main/config.go +77 -0
- data/go/src/boshprovisioner/main/main.go +183 -0
- data/go/src/boshprovisioner/main/repos_factory.go +96 -0
- data/go/src/boshprovisioner/packagescompiler/compiledpackagesrepo/compiled_packages_repository_interface.go +17 -0
- data/go/src/boshprovisioner/packagescompiler/compiledpackagesrepo/concrete_compiled_packages_repository.go +61 -0
- data/go/src/boshprovisioner/packagescompiler/concrete_packages_compiler.go +179 -0
- data/go/src/boshprovisioner/packagescompiler/concrete_packages_compiler_factory.go +48 -0
- data/go/src/boshprovisioner/packagescompiler/packages_compiler_interface.go +20 -0
- data/go/src/boshprovisioner/packagescompiler/packagesrepo/concrete_packages_repository.go +65 -0
- data/go/src/boshprovisioner/packagescompiler/packagesrepo/packages_repository_interface.go +16 -0
- data/go/src/boshprovisioner/provisioner/blobstore_config.go +65 -0
- data/go/src/boshprovisioner/provisioner/blobstore_provisioner.go +38 -0
- data/go/src/boshprovisioner/provisioner/deployment_provisioner.go +97 -0
- data/go/src/boshprovisioner/provisioner/instance_provisioner.go +48 -0
- data/go/src/boshprovisioner/provisioner/release_compiler.go +133 -0
- data/go/src/boshprovisioner/release/job/job.go +86 -0
- data/go/src/boshprovisioner/release/job/manifest/manifest.go +79 -0
- data/go/src/boshprovisioner/release/job/manifest/manifest_suite_test.go +13 -0
- data/go/src/boshprovisioner/release/job/manifest/manifest_test.go +42 -0
- data/go/src/boshprovisioner/release/job/manifest/syntax_validator.go +43 -0
- data/go/src/boshprovisioner/release/job/reader_factory.go +34 -0
- data/go/src/boshprovisioner/release/job/tar_reader.go +133 -0
- data/go/src/boshprovisioner/release/manifest/manifest.go +96 -0
- data/go/src/boshprovisioner/release/manifest_reader.go +29 -0
- data/go/src/boshprovisioner/release/reader_factory.go +34 -0
- data/go/src/boshprovisioner/release/release.go +144 -0
- data/go/src/boshprovisioner/release/release_suite_test.go +13 -0
- data/go/src/boshprovisioner/release/release_test.go +129 -0
- data/go/src/boshprovisioner/release/tar_reader.go +139 -0
- data/go/src/boshprovisioner/releasesrepo/blobstore_releases_repository.go +114 -0
- data/go/src/boshprovisioner/releasesrepo/releases_repository_interface.go +15 -0
- data/go/src/boshprovisioner/tar/cmd_compressor.go +68 -0
- data/go/src/boshprovisioner/tar/cmd_extractor.go +47 -0
- data/go/src/boshprovisioner/tar/compressor_interface.go +6 -0
- data/go/src/boshprovisioner/tar/extractor_interface.go +6 -0
- data/go/src/boshprovisioner/util/string_keyed.go +70 -0
- data/go/src/boshprovisioner/vm/agent_provisioner.go +266 -0
- data/go/src/boshprovisioner/vm/asset_manager.go +61 -0
- data/go/src/boshprovisioner/vm/deps_provisioner.go +92 -0
- data/go/src/boshprovisioner/vm/monit_provisioner.go +83 -0
- data/go/src/boshprovisioner/vm/runit_provisioner.go +225 -0
- data/go/src/boshprovisioner/vm/simple_cmds.go +54 -0
- data/go/src/boshprovisioner/vm/vcap_user_provisioner.go +120 -0
- data/go/src/boshprovisioner/vm/vm.go +19 -0
- data/go/src/boshprovisioner/vm/vm_provisioner.go +57 -0
- data/go/src/boshprovisioner/vm/vm_provisioner_factory.go +97 -0
- data/lib/vagrant-bosh/asset_uploader.rb +53 -0
- data/lib/vagrant-bosh/assets/agent/agent-log +5 -0
- data/lib/vagrant-bosh/assets/agent/agent-run +12 -0
- data/lib/vagrant-bosh/assets/agent/agent.cert +18 -0
- data/lib/vagrant-bosh/assets/agent/agent.json +9 -0
- data/lib/vagrant-bosh/assets/agent/agent.key +27 -0
- data/lib/vagrant-bosh/assets/agent/bosh-agent +0 -0
- data/lib/vagrant-bosh/assets/agent/bosh-agent-rc +18 -0
- data/lib/vagrant-bosh/assets/agent/bosh-blobstore-dav +0 -0
- data/lib/vagrant-bosh/assets/monit/monit +0 -0
- data/lib/vagrant-bosh/assets/monit/monit-log +5 -0
- data/lib/vagrant-bosh/assets/monit/monit-run +9 -0
- data/lib/vagrant-bosh/assets/monit/monitrc +8 -0
- data/lib/vagrant-bosh/assets/provisioner +0 -0
- data/lib/vagrant-bosh/bootstrapper.rb +59 -0
- data/lib/vagrant-bosh/communicator.rb +50 -0
- data/lib/vagrant-bosh/config.rb +15 -0
- data/lib/vagrant-bosh/errors.rb +11 -0
- data/lib/vagrant-bosh/plugin.rb +25 -0
- data/lib/vagrant-bosh/provisioner.rb +46 -0
- data/lib/vagrant-bosh/provisioner_tracker.rb +41 -0
- data/lib/vagrant-bosh/ui.rb +77 -0
- data/lib/vagrant-bosh/version.rb +5 -0
- data/lib/vagrant-bosh.rb +15 -0
- data/templates/locales/en.yml +15 -0
- data/vagrant-bosh.gemspec +20 -0
- metadata +191 -0
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
package templatescompiler
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"fmt"
|
|
5
|
+
|
|
6
|
+
boshblob "bosh/blobstore"
|
|
7
|
+
bosherr "bosh/errors"
|
|
8
|
+
boshlog "bosh/logger"
|
|
9
|
+
|
|
10
|
+
bpdep "boshprovisioner/deployment"
|
|
11
|
+
bpjobsrepo "boshprovisioner/instance/templatescompiler/jobsrepo"
|
|
12
|
+
bptplsrepo "boshprovisioner/instance/templatescompiler/templatesrepo"
|
|
13
|
+
bprel "boshprovisioner/release"
|
|
14
|
+
bpreljob "boshprovisioner/release/job"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
type ConcreteTemplatesCompiler struct {
|
|
18
|
+
renderedArchivesCompiler RenderedArchivesCompiler
|
|
19
|
+
jobReaderFactory bpreljob.ReaderFactory
|
|
20
|
+
|
|
21
|
+
jobsRepo bpjobsrepo.JobsRepository
|
|
22
|
+
tplToJobRepo bpjobsrepo.TemplateToJobRepository
|
|
23
|
+
runPkgsRepo bpjobsrepo.RuntimePackagesRepository
|
|
24
|
+
templatesRepo bptplsrepo.TemplatesRepository
|
|
25
|
+
|
|
26
|
+
blobstore boshblob.Blobstore
|
|
27
|
+
logger boshlog.Logger
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
func NewConcreteTemplatesCompiler(
|
|
31
|
+
renderedArchivesCompiler RenderedArchivesCompiler,
|
|
32
|
+
jobReaderFactory bpreljob.ReaderFactory,
|
|
33
|
+
jobsRepo bpjobsrepo.JobsRepository,
|
|
34
|
+
tplToJobRepo bpjobsrepo.TemplateToJobRepository,
|
|
35
|
+
runPkgsRepo bpjobsrepo.RuntimePackagesRepository,
|
|
36
|
+
templatesRepo bptplsrepo.TemplatesRepository,
|
|
37
|
+
blobstore boshblob.Blobstore,
|
|
38
|
+
logger boshlog.Logger,
|
|
39
|
+
) ConcreteTemplatesCompiler {
|
|
40
|
+
return ConcreteTemplatesCompiler{
|
|
41
|
+
renderedArchivesCompiler: renderedArchivesCompiler,
|
|
42
|
+
jobReaderFactory: jobReaderFactory,
|
|
43
|
+
|
|
44
|
+
jobsRepo: jobsRepo,
|
|
45
|
+
tplToJobRepo: tplToJobRepo,
|
|
46
|
+
runPkgsRepo: runPkgsRepo,
|
|
47
|
+
templatesRepo: templatesRepo,
|
|
48
|
+
|
|
49
|
+
blobstore: blobstore,
|
|
50
|
+
logger: logger,
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Precompile prepares release jobs to be later combined with instance properties
|
|
55
|
+
func (tc ConcreteTemplatesCompiler) Precompile(release bprel.Release) error {
|
|
56
|
+
var allPkgs []bprel.Package
|
|
57
|
+
|
|
58
|
+
for _, pkg := range release.Packages {
|
|
59
|
+
if pkg == nil {
|
|
60
|
+
// todo panic or should not be here?
|
|
61
|
+
return bosherr.New("Expected release to not have nil package")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
allPkgs = append(allPkgs, *pkg)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
for _, job := range release.Jobs {
|
|
68
|
+
jobRec, found, err := tc.jobsRepo.Find(job)
|
|
69
|
+
if err != nil {
|
|
70
|
+
return bosherr.WrapError(err, "Finding job source blob %s", job.Name)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if !found {
|
|
74
|
+
blobID, fingerprint, err := tc.blobstore.Create(job.TarPath)
|
|
75
|
+
if err != nil {
|
|
76
|
+
return bosherr.WrapError(err, "Creating job source blob %s", job.Name)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
jobRec = bpjobsrepo.JobRecord{
|
|
80
|
+
BlobID: blobID,
|
|
81
|
+
SHA1: fingerprint,
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
err = tc.jobsRepo.Save(job, jobRec)
|
|
85
|
+
if err != nil {
|
|
86
|
+
return bosherr.WrapError(err, "Saving job record %s", job.Name)
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
err = tc.tplToJobRepo.SaveForJob(release, job)
|
|
91
|
+
if err != nil {
|
|
92
|
+
return bosherr.WrapError(err, "Saving release job %s", job.Name)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// todo associate to release instead
|
|
96
|
+
err = tc.runPkgsRepo.SaveAllForReleaseJob(job, allPkgs)
|
|
97
|
+
if err != nil {
|
|
98
|
+
return bosherr.WrapError(err, "Saving release job %s", job.Name)
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return nil
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Compile populates blobstore with rendered jobs for a given deployment instance.
|
|
106
|
+
func (tc ConcreteTemplatesCompiler) Compile(job bpdep.Job, instance bpdep.Instance) error {
|
|
107
|
+
relJobReaders, err := tc.buildJobReaders(job)
|
|
108
|
+
if err != nil {
|
|
109
|
+
return err
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
blobID, fingerprint, err := tc.compileJob(relJobReaders, instance)
|
|
113
|
+
if err != nil {
|
|
114
|
+
return err
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
templateRec := bptplsrepo.TemplateRecord{
|
|
118
|
+
BlobID: blobID,
|
|
119
|
+
SHA1: fingerprint,
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
err = tc.templatesRepo.Save(job, instance, templateRec)
|
|
123
|
+
if err != nil {
|
|
124
|
+
return bosherr.WrapError(err, "Saving compiled templates record %s", job.Name)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return nil
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// FindPackages returns list of packages required to run job template.
|
|
131
|
+
// List of packages is usually specified in release job metadata.
|
|
132
|
+
func (tc ConcreteTemplatesCompiler) FindPackages(template bpdep.Template) ([]bprel.Package, error) {
|
|
133
|
+
var pkgs []bprel.Package
|
|
134
|
+
|
|
135
|
+
job, found, err := tc.tplToJobRepo.FindByTemplate(template)
|
|
136
|
+
if err != nil {
|
|
137
|
+
return pkgs, bosherr.WrapError(err, "Finding job by template %s", template.Name)
|
|
138
|
+
} else if !found {
|
|
139
|
+
return pkgs, bosherr.New("Expected to find job by template %s", template.Name)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
pkgs, found, err = tc.runPkgsRepo.FindByReleaseJob(job)
|
|
143
|
+
if err != nil {
|
|
144
|
+
return pkgs, bosherr.WrapError(err, "Finding packages by job %s", job.Name)
|
|
145
|
+
} else if !found {
|
|
146
|
+
return pkgs, bosherr.New("Expected to find packages by job %s", job.Name)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return pkgs, nil
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// FindRenderedArchive returns previously compiled template for a given instance.
|
|
153
|
+
// If such compiled template is not found, error is returned.
|
|
154
|
+
func (tc ConcreteTemplatesCompiler) FindRenderedArchive(job bpdep.Job, instance bpdep.Instance) (RenderedArchiveRecord, error) {
|
|
155
|
+
var renderedArchiveRec RenderedArchiveRecord
|
|
156
|
+
|
|
157
|
+
rec, found, err := tc.templatesRepo.Find(job, instance)
|
|
158
|
+
if err != nil {
|
|
159
|
+
return renderedArchiveRec, bosherr.WrapError(err, "Finding compiled templates %s", job.Name)
|
|
160
|
+
} else if !found {
|
|
161
|
+
return renderedArchiveRec, bosherr.New("Expected to find compiled templates %s", job.Name)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
renderedArchiveRec.SHA1 = rec.SHA1
|
|
165
|
+
renderedArchiveRec.BlobID = rec.BlobID
|
|
166
|
+
|
|
167
|
+
return renderedArchiveRec, nil
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
type jobReader struct {
|
|
171
|
+
relJob bprel.Job
|
|
172
|
+
tarReader *bpreljob.TarReader
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
func (tc ConcreteTemplatesCompiler) buildJobReaders(job bpdep.Job) ([]jobReader, error) {
|
|
176
|
+
var readers []jobReader
|
|
177
|
+
|
|
178
|
+
for _, template := range job.Templates {
|
|
179
|
+
relJob, found, err := tc.tplToJobRepo.FindByTemplate(template)
|
|
180
|
+
if err != nil {
|
|
181
|
+
return readers, bosherr.WrapError(err, "Finding dep-template -> rel-job %s", template.Name)
|
|
182
|
+
} else if !found {
|
|
183
|
+
return readers, bosherr.New("Expected to find dep-template -> rel-job %s", template.Name)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
jobRec, found, err := tc.jobsRepo.Find(relJob)
|
|
187
|
+
if err != nil {
|
|
188
|
+
return readers, bosherr.WrapError(err, "Finding job source blob %s", template.Name)
|
|
189
|
+
} else if !found {
|
|
190
|
+
return readers, bosherr.New("Expected to find job source blob %s", template.Name)
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
jobURL := fmt.Sprintf("blobstore:///%s?fingerprint=%s", jobRec.BlobID, jobRec.SHA1)
|
|
194
|
+
|
|
195
|
+
reader := jobReader{
|
|
196
|
+
relJob: relJob,
|
|
197
|
+
tarReader: tc.jobReaderFactory.NewTarReader(jobURL),
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
readers = append(readers, reader)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return readers, nil
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// compileJob produces and saves rendered templates archive to a blobstore.
|
|
207
|
+
func (tc ConcreteTemplatesCompiler) compileJob(jobReaders []jobReader, instance bpdep.Instance) (string, string, error) {
|
|
208
|
+
var relJobs []bpreljob.Job
|
|
209
|
+
|
|
210
|
+
for _, jobReader := range jobReaders {
|
|
211
|
+
relJob, err := jobReader.tarReader.Read()
|
|
212
|
+
if err != nil {
|
|
213
|
+
return "", "", bosherr.WrapError(err, "Reading job")
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
defer jobReader.tarReader.Close()
|
|
217
|
+
|
|
218
|
+
err = tc.associatePackages(jobReader.relJob, relJob)
|
|
219
|
+
if err != nil {
|
|
220
|
+
return "", "", bosherr.WrapError(err, "Preparing runtime dep packages")
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
relJobs = append(relJobs, relJob)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
renderedArchivePath, err := tc.renderedArchivesCompiler.Compile(relJobs, instance)
|
|
227
|
+
if err != nil {
|
|
228
|
+
return "", "", bosherr.WrapError(err, "Compiling templates")
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
defer tc.renderedArchivesCompiler.CleanUp(renderedArchivePath)
|
|
232
|
+
|
|
233
|
+
blobID, fingerprint, err := tc.blobstore.Create(renderedArchivePath)
|
|
234
|
+
if err != nil {
|
|
235
|
+
return "", "", bosherr.WrapError(err, "Creating compiled templates")
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return blobID, fingerprint, nil
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
func (tc ConcreteTemplatesCompiler) associatePackages(rJob bprel.Job, relJob bpreljob.Job) error {
|
|
242
|
+
_, found, err := tc.runPkgsRepo.FindByReleaseJob(rJob)
|
|
243
|
+
if err != nil {
|
|
244
|
+
return bosherr.WrapError(err, "Finding runtime deps for %s", rJob.Name)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if !found {
|
|
248
|
+
allPkgs, found, err := tc.runPkgsRepo.FindAllByReleaseJob(rJob)
|
|
249
|
+
if err != nil {
|
|
250
|
+
return bosherr.WrapError(err, "Finding rel-job -> rel-pkgs %s", rJob.Name)
|
|
251
|
+
} else if !found {
|
|
252
|
+
return bosherr.New("Expected to find rel-job -> rel-pkgs %s", rJob.Name)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
var pkgs []bprel.Package
|
|
256
|
+
|
|
257
|
+
for _, pkg := range allPkgs {
|
|
258
|
+
for _, p := range relJob.Packages {
|
|
259
|
+
if pkg.Name == p.Name {
|
|
260
|
+
pkgs = append(pkgs, pkg)
|
|
261
|
+
break
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
err = tc.runPkgsRepo.SaveForReleaseJob(rJob, pkgs)
|
|
267
|
+
if err != nil {
|
|
268
|
+
return bosherr.WrapError(err, "Saving job packages %s", rJob.Name)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
return nil
|
|
273
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
package erbrenderer
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"os"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
|
|
8
|
+
bosherr "bosh/errors"
|
|
9
|
+
boshlog "bosh/logger"
|
|
10
|
+
boshsys "bosh/system"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
const erbRendererLogTag = "ERBRenderer"
|
|
14
|
+
|
|
15
|
+
type ERBRenderer struct {
|
|
16
|
+
fs boshsys.FileSystem
|
|
17
|
+
runner boshsys.CmdRunner
|
|
18
|
+
context TemplateEvaluationContext
|
|
19
|
+
logger boshlog.Logger
|
|
20
|
+
|
|
21
|
+
rendererScript string
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
func NewERBRenderer(
|
|
25
|
+
fs boshsys.FileSystem,
|
|
26
|
+
runner boshsys.CmdRunner,
|
|
27
|
+
context TemplateEvaluationContext,
|
|
28
|
+
logger boshlog.Logger,
|
|
29
|
+
) ERBRenderer {
|
|
30
|
+
return ERBRenderer{
|
|
31
|
+
fs: fs,
|
|
32
|
+
runner: runner,
|
|
33
|
+
context: context,
|
|
34
|
+
logger: logger,
|
|
35
|
+
|
|
36
|
+
rendererScript: templateEvaluationContextRb,
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func (r ERBRenderer) Render(srcPath, dstPath string) error {
|
|
41
|
+
r.logger.Debug(erbRendererLogTag, "Rendering template %s", dstPath)
|
|
42
|
+
|
|
43
|
+
dirPath := filepath.Dir(dstPath)
|
|
44
|
+
|
|
45
|
+
err := r.fs.MkdirAll(dirPath, os.FileMode(0755))
|
|
46
|
+
if err != nil {
|
|
47
|
+
return bosherr.WrapError(err, "Creating directory %s", dirPath)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
rendererScriptPath, err := r.writeRendererScript()
|
|
51
|
+
if err != nil {
|
|
52
|
+
return err
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
contextPath, err := r.writeContext()
|
|
56
|
+
if err != nil {
|
|
57
|
+
return err
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Use ruby to compile job templates
|
|
61
|
+
command := boshsys.Command{
|
|
62
|
+
Name: r.determineRubyExePath(),
|
|
63
|
+
Args: []string{rendererScriptPath, contextPath, srcPath, dstPath},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_, _, _, err = r.runner.RunComplexCommand(command)
|
|
67
|
+
if err != nil {
|
|
68
|
+
return bosherr.WrapError(err, "Running ruby")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return nil
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
func (r ERBRenderer) writeRendererScript() (string, error) {
|
|
75
|
+
// todo use temp path; it's same everytime?
|
|
76
|
+
path := "/tmp/erb-render.rb"
|
|
77
|
+
|
|
78
|
+
err := r.fs.WriteFileString(path, r.rendererScript)
|
|
79
|
+
if err != nil {
|
|
80
|
+
return "", bosherr.WrapError(err, "Writing renderer script")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return path, nil
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
func (r ERBRenderer) writeContext() (string, error) {
|
|
87
|
+
contextBytes, err := json.Marshal(r.context)
|
|
88
|
+
if err != nil {
|
|
89
|
+
return "", bosherr.WrapError(err, "Marshalling context")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// todo use temp path?
|
|
93
|
+
path := "/tmp/erb-context.json"
|
|
94
|
+
|
|
95
|
+
err = r.fs.WriteFileString(path, string(contextBytes))
|
|
96
|
+
if err != nil {
|
|
97
|
+
return "", bosherr.WrapError(err, "Writing context")
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return path, nil
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
func (r ERBRenderer) determineRubyExePath() string {
|
|
104
|
+
// Prefer ruby executable on the PATH
|
|
105
|
+
if r.runner.CommandExists("ruby") {
|
|
106
|
+
return "ruby"
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Fallback to chef-solo ruby usually found in vagrant boxes
|
|
110
|
+
vagrantRuby := "/opt/vagrant_ruby/bin/ruby"
|
|
111
|
+
|
|
112
|
+
if r.fs.FileExists(vagrantRuby) {
|
|
113
|
+
return vagrantRuby
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return "ruby"
|
|
117
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
package erbrenderer
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"strings"
|
|
6
|
+
|
|
7
|
+
bosherr "bosh/errors"
|
|
8
|
+
|
|
9
|
+
bpdep "boshprovisioner/deployment"
|
|
10
|
+
bpreljob "boshprovisioner/release/job"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
type RenderProperties struct {
|
|
14
|
+
relJob bpreljob.Job
|
|
15
|
+
instance bpdep.Instance
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
func NewRenderProperties(relJob bpreljob.Job, instance bpdep.Instance) RenderProperties {
|
|
19
|
+
return RenderProperties{relJob: relJob, instance: instance}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// AsMap returns job and instance properties merged together.
|
|
23
|
+
func (p RenderProperties) AsMap() (map[string]interface{}, error) {
|
|
24
|
+
result, err := p.deepCopyInstanceProperties()
|
|
25
|
+
if err != nil {
|
|
26
|
+
return result, err
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
for _, prop := range p.relJob.Properties {
|
|
30
|
+
p.copyProperty(prop.Name, prop.Default, result)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return result, nil
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// copyProperty fills in property in dst with value if it's not already set.
|
|
37
|
+
func (p RenderProperties) copyProperty(path string, value interface{}, dst map[string]interface{}) {
|
|
38
|
+
pathParts := strings.Split(path, ".")
|
|
39
|
+
|
|
40
|
+
for i, part := range pathParts {
|
|
41
|
+
if dstNested, ok := dst[part]; ok { // Found section; check if modified
|
|
42
|
+
if dstNestedMap, ok := dstNested.(map[string]interface{}); ok {
|
|
43
|
+
dst = dstNestedMap
|
|
44
|
+
} else {
|
|
45
|
+
break // Not a section; cannot modify
|
|
46
|
+
}
|
|
47
|
+
} else if len(pathParts)-1 == i { // Last property path part
|
|
48
|
+
dst[part] = value
|
|
49
|
+
} else {
|
|
50
|
+
m := map[string]interface{}{}
|
|
51
|
+
dst[part] = m
|
|
52
|
+
dst = m
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// deepCopyInstanceProperties makes a deep copy of instance properties.
|
|
58
|
+
// Always returns an initialized map even if instance properties are nil.
|
|
59
|
+
func (p RenderProperties) deepCopyInstanceProperties() (map[string]interface{}, error) {
|
|
60
|
+
result := map[string]interface{}{}
|
|
61
|
+
|
|
62
|
+
if p.instance.Properties == nil {
|
|
63
|
+
return result, nil
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
bytes, err := json.Marshal(p.instance.Properties)
|
|
67
|
+
if err != nil {
|
|
68
|
+
return result, bosherr.WrapError(err, "Marshalling instance properties")
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
err = json.Unmarshal(bytes, &result)
|
|
72
|
+
if err != nil {
|
|
73
|
+
return result, bosherr.WrapError(err, "Unmarshalling instance properties")
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return result, nil
|
|
77
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
package erbrenderer_test
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
. "github.com/onsi/ginkgo"
|
|
5
|
+
. "github.com/onsi/gomega"
|
|
6
|
+
|
|
7
|
+
bpdep "boshprovisioner/deployment"
|
|
8
|
+
. "boshprovisioner/instance/templatescompiler/erbrenderer"
|
|
9
|
+
bpreljob "boshprovisioner/release/job"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
var _ = Describe("RenderProperties", func() {
|
|
13
|
+
var (
|
|
14
|
+
job bpreljob.Job
|
|
15
|
+
instance bpdep.Instance
|
|
16
|
+
props RenderProperties
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
JustBeforeEach(func() {
|
|
20
|
+
props = NewRenderProperties(job, instance)
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
Describe("AsMap", func() {
|
|
24
|
+
Context("when job specifies a default for a nested property", func() {
|
|
25
|
+
BeforeEach(func() {
|
|
26
|
+
job = bpreljob.Job{
|
|
27
|
+
Properties: []bpreljob.Property{
|
|
28
|
+
bpreljob.Property{
|
|
29
|
+
Name: "prop.nest-prop",
|
|
30
|
+
Default: "job-val",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
Context("when instance specifies nested property", func() {
|
|
37
|
+
BeforeEach(func() {
|
|
38
|
+
instance = bpdep.Instance{
|
|
39
|
+
Properties: map[string]interface{}{
|
|
40
|
+
"prop": map[string]interface{}{
|
|
41
|
+
"nest-prop": "instance-val",
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
It("returns map with property value from job", func() {
|
|
48
|
+
Expect(props.AsMap()).To(Equal(map[string]interface{}{
|
|
49
|
+
"prop": map[string]interface{}{
|
|
50
|
+
"nest-prop": "instance-val",
|
|
51
|
+
},
|
|
52
|
+
}))
|
|
53
|
+
})
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
Context("when instance does not specify nested property", func() {
|
|
57
|
+
Context("when first nesting level is specified", func() {
|
|
58
|
+
BeforeEach(func() {
|
|
59
|
+
instance = bpdep.Instance{
|
|
60
|
+
Properties: map[string]interface{}{
|
|
61
|
+
"prop": map[string]interface{}{},
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
It("returns map with default property from job", func() {
|
|
67
|
+
Expect(props.AsMap()).To(Equal(map[string]interface{}{
|
|
68
|
+
"prop": map[string]interface{}{
|
|
69
|
+
"nest-prop": "job-val",
|
|
70
|
+
},
|
|
71
|
+
}))
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
Context("when first nesting level is not specified", func() {
|
|
76
|
+
BeforeEach(func() {
|
|
77
|
+
instance = bpdep.Instance{}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
It("returns map with default property from job", func() {
|
|
81
|
+
Expect(props.AsMap()).To(Equal(map[string]interface{}{
|
|
82
|
+
"prop": map[string]interface{}{
|
|
83
|
+
"nest-prop": "job-val",
|
|
84
|
+
},
|
|
85
|
+
}))
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
})
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
Context("when job does not specify a default (nil) for a nested property", func() {
|
|
92
|
+
BeforeEach(func() {
|
|
93
|
+
job = bpreljob.Job{
|
|
94
|
+
Properties: []bpreljob.Property{
|
|
95
|
+
bpreljob.Property{
|
|
96
|
+
Name: "prop.nest-prop",
|
|
97
|
+
Default: nil,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
Context("when instance specifies nested property", func() {
|
|
104
|
+
BeforeEach(func() {
|
|
105
|
+
instance = bpdep.Instance{
|
|
106
|
+
Properties: map[string]interface{}{
|
|
107
|
+
"prop": map[string]interface{}{
|
|
108
|
+
"nest-prop": "instance-val",
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
}
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
It("returns map with property value from instance", func() {
|
|
115
|
+
Expect(props.AsMap()).To(Equal(map[string]interface{}{
|
|
116
|
+
"prop": map[string]interface{}{
|
|
117
|
+
"nest-prop": "instance-val",
|
|
118
|
+
},
|
|
119
|
+
}))
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
Context("when instance does not specify nested property", func() {
|
|
124
|
+
BeforeEach(func() {
|
|
125
|
+
instance = bpdep.Instance{
|
|
126
|
+
Properties: map[string]interface{}{
|
|
127
|
+
"prop": map[string]interface{}{},
|
|
128
|
+
},
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
It("returns map with default property from job", func() {
|
|
133
|
+
Expect(props.AsMap()).To(Equal(map[string]interface{}{
|
|
134
|
+
"prop": map[string]interface{}{
|
|
135
|
+
"nest-prop": nil,
|
|
136
|
+
},
|
|
137
|
+
}))
|
|
138
|
+
})
|
|
139
|
+
})
|
|
140
|
+
}) //~
|
|
141
|
+
})
|
|
142
|
+
})
|
data/go/src/boshprovisioner/instance/templatescompiler/erbrenderer/template_evaluation_context.go
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
package erbrenderer
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
|
|
6
|
+
bosherr "bosh/errors"
|
|
7
|
+
|
|
8
|
+
bpdep "boshprovisioner/deployment"
|
|
9
|
+
bpreljob "boshprovisioner/release/job"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
type TemplateEvaluationContext struct {
|
|
13
|
+
relJob bpreljob.Job
|
|
14
|
+
instance bpdep.Instance
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// rootContext is exposed as an open struct in ERB templates.
|
|
18
|
+
// It must stay same to provide backwards compatible API.
|
|
19
|
+
type rootContext struct {
|
|
20
|
+
Index int `json:"index"`
|
|
21
|
+
|
|
22
|
+
JobContext jobContext `json:"job"`
|
|
23
|
+
|
|
24
|
+
Deployment string `json:"deployment"`
|
|
25
|
+
|
|
26
|
+
// Usually is accessed with <%= spec.networks.default.ip %>
|
|
27
|
+
NetworkContexts map[string]networkContext `json:"networks"`
|
|
28
|
+
|
|
29
|
+
Properties map[string]interface{} `json:"properties"`
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
type jobContext struct {
|
|
33
|
+
Name string `json:"name"`
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// networkContext is not fully backwards compatible.
|
|
37
|
+
type networkContext struct {
|
|
38
|
+
IP string `json:"ip"`
|
|
39
|
+
Netmask string `json:"netmask"`
|
|
40
|
+
Gateway string `json:"gateway"`
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
func NewTemplateEvaluationContext(
|
|
44
|
+
relJob bpreljob.Job,
|
|
45
|
+
instance bpdep.Instance,
|
|
46
|
+
) TemplateEvaluationContext {
|
|
47
|
+
return TemplateEvaluationContext{
|
|
48
|
+
relJob: relJob,
|
|
49
|
+
instance: instance,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func (c TemplateEvaluationContext) MarshalJSON() ([]byte, error) {
|
|
54
|
+
properties, err := NewRenderProperties(c.relJob, c.instance).AsMap()
|
|
55
|
+
if err != nil {
|
|
56
|
+
return nil, bosherr.WrapError(err, "Rendering properties")
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
context := rootContext{
|
|
60
|
+
Index: c.instance.Index,
|
|
61
|
+
JobContext: jobContext{Name: c.instance.JobName},
|
|
62
|
+
Deployment: c.instance.DeploymentName,
|
|
63
|
+
|
|
64
|
+
NetworkContexts: c.buildNetworkContexts(),
|
|
65
|
+
Properties: properties,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return json.Marshal(context)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
func (c TemplateEvaluationContext) buildNetworkContexts() map[string]networkContext {
|
|
72
|
+
networkContexts := map[string]networkContext{}
|
|
73
|
+
|
|
74
|
+
for _, na := range c.instance.NetworkAssociations {
|
|
75
|
+
netConfig := c.instance.NetworkConfigurationForNetworkAssociation(na)
|
|
76
|
+
|
|
77
|
+
networkContexts[na.Network.Name] = networkContext{
|
|
78
|
+
IP: netConfig.IP,
|
|
79
|
+
Netmask: netConfig.Netmask,
|
|
80
|
+
Gateway: netConfig.Gateway,
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return networkContexts
|
|
85
|
+
}
|