vagrant-bosh 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,34 @@
1
+ package release
2
+
3
+ import (
4
+ boshlog "bosh/logger"
5
+ boshsys "bosh/system"
6
+
7
+ bpdload "boshprovisioner/downloader"
8
+ bptar "boshprovisioner/tar"
9
+ )
10
+
11
+ type ReaderFactory struct {
12
+ downloader bpdload.Downloader
13
+ extractor bptar.Extractor
14
+ fs boshsys.FileSystem
15
+ logger boshlog.Logger
16
+ }
17
+
18
+ func NewReaderFactory(
19
+ downloader bpdload.Downloader,
20
+ extractor bptar.Extractor,
21
+ fs boshsys.FileSystem,
22
+ logger boshlog.Logger,
23
+ ) ReaderFactory {
24
+ return ReaderFactory{
25
+ downloader: downloader,
26
+ extractor: extractor,
27
+ fs: fs,
28
+ logger: logger,
29
+ }
30
+ }
31
+
32
+ func (rf ReaderFactory) NewTarReader(path string) *TarReader {
33
+ return NewTarReader(path, rf.downloader, rf.extractor, rf.fs, rf.logger)
34
+ }
@@ -0,0 +1,144 @@
1
+ package release
2
+
3
+ import (
4
+ bprelman "boshprovisioner/release/manifest"
5
+ )
6
+
7
+ type Release struct {
8
+ Manifest bprelman.Manifest
9
+
10
+ Name string
11
+ Version string
12
+
13
+ Jobs []Job
14
+
15
+ Packages []*Package
16
+ }
17
+
18
+ type Job struct {
19
+ Name string
20
+ Version string
21
+
22
+ Fingerprint string
23
+ SHA1 string
24
+
25
+ TarPath string
26
+ }
27
+
28
+ type Package struct {
29
+ Name string
30
+ Version string
31
+
32
+ Fingerprint string
33
+ SHA1 string
34
+
35
+ TarPath string
36
+
37
+ // Package dependencies used at compilation of this package
38
+ Dependencies []*Package
39
+ }
40
+
41
+ // ResolvedPackageDependencies returns list of packages
42
+ // in order such that each package at a higher index
43
+ // only depends on packages at lower indecies.
44
+ func (r Release) ResolvedPackageDependencies() []*Package {
45
+ var resolvedPkgs []*Package
46
+ var pendingPkgs []*Package
47
+
48
+ for _, pkg := range r.Packages {
49
+ pkgRef := pkg
50
+ pendingPkgs = append(pendingPkgs, pkgRef)
51
+ }
52
+
53
+ iterations := 0
54
+
55
+ for len(pendingPkgs) > 0 {
56
+ pkg := pendingPkgs[0]
57
+
58
+ depsSatisfied := true
59
+
60
+ for _, depPkg := range pkg.Dependencies {
61
+ depSatisfied := false
62
+
63
+ for _, resPkg := range resolvedPkgs {
64
+ if depPkg.Name == resPkg.Name {
65
+ depSatisfied = true
66
+ break
67
+ }
68
+ }
69
+
70
+ if !depSatisfied {
71
+ depsSatisfied = false
72
+ break
73
+ }
74
+ }
75
+
76
+ pendingPkgs = pendingPkgs[1:]
77
+ if depsSatisfied {
78
+ resolvedPkgs = append(resolvedPkgs, pkg)
79
+ } else {
80
+ pendingPkgs = append(pendingPkgs, pkg)
81
+ }
82
+
83
+ if iterations > 100 {
84
+ panic("Failed to resolve package dependenices witin 100 iterations")
85
+ } else {
86
+ iterations++
87
+ }
88
+ }
89
+
90
+ return resolvedPkgs
91
+ }
92
+
93
+ // populateFromManifest populates release information
94
+ // interpreted from release manifest.
95
+ func (r *Release) populateFromManifest(manifest bprelman.Manifest) {
96
+ r.populateRelease(manifest.Release)
97
+ r.populatePackages(manifest.Release.Packages)
98
+ r.populateJobs(manifest.Release.Jobs)
99
+ r.Manifest = manifest
100
+ }
101
+
102
+ func (r *Release) populateRelease(manRelease bprelman.Release) {
103
+ r.Name = manRelease.Name
104
+ r.Version = manRelease.Version
105
+ }
106
+
107
+ func (r *Release) populatePackages(manPkgs []bprelman.Package) {
108
+ nameToPkg := map[bprelman.DependencyName]*Package{}
109
+
110
+ for _, manPkg := range manPkgs {
111
+ pkg := Package{
112
+ Name: manPkg.Name,
113
+ Version: manPkg.Version,
114
+
115
+ Fingerprint: manPkg.Fingerprint,
116
+ SHA1: manPkg.SHA1,
117
+ }
118
+
119
+ r.Packages = append(r.Packages, &pkg)
120
+
121
+ nameToPkg[bprelman.DependencyName(pkg.Name)] = &pkg
122
+ }
123
+
124
+ // Connect compile time dependencies for packages
125
+ for i, manPkg := range manPkgs {
126
+ for _, depName := range manPkg.DependencyNames {
127
+ r.Packages[i].Dependencies = append(r.Packages[i].Dependencies, nameToPkg[depName])
128
+ }
129
+ }
130
+ }
131
+
132
+ func (r *Release) populateJobs(manJobs []bprelman.Job) {
133
+ for _, manJob := range manJobs {
134
+ job := Job{
135
+ Name: manJob.Name,
136
+ Version: manJob.Version,
137
+
138
+ Fingerprint: manJob.Fingerprint,
139
+ SHA1: manJob.SHA1,
140
+ }
141
+
142
+ r.Jobs = append(r.Jobs, job)
143
+ }
144
+ }
@@ -0,0 +1,13 @@
1
+ package release_test
2
+
3
+ import (
4
+ . "github.com/onsi/ginkgo"
5
+ . "github.com/onsi/gomega"
6
+
7
+ "testing"
8
+ )
9
+
10
+ func TestRelease(t *testing.T) {
11
+ RegisterFailHandler(Fail)
12
+ RunSpecs(t, "Release Suite")
13
+ }
@@ -0,0 +1,129 @@
1
+ package release_test
2
+
3
+ import (
4
+ . "github.com/onsi/ginkgo"
5
+ . "github.com/onsi/gomega"
6
+
7
+ . "boshprovisioner/release"
8
+ )
9
+
10
+ var _ = Describe("Release", func() {
11
+ var (
12
+ release Release
13
+ )
14
+
15
+ BeforeEach(func() {
16
+ release = Release{}
17
+ })
18
+
19
+ Describe("ResolvedPackageDependencies", func() {
20
+ It("returns packages in correct order with transitive deps", func() {
21
+ pkg1 := Package{Name: "fake-package-name-1"}
22
+
23
+ pkg2 := Package{
24
+ Name: "fake-package-name-2",
25
+ Dependencies: []*Package{&pkg1},
26
+ }
27
+
28
+ pkg3 := Package{
29
+ Name: "fake-package-name-3",
30
+ Dependencies: []*Package{&pkg2},
31
+ }
32
+
33
+ release.Packages = []*Package{&pkg3, &pkg2, &pkg1}
34
+
35
+ pkgs := release.ResolvedPackageDependencies()
36
+ Expect(pkgs).To(Equal([]*Package{&pkg1, &pkg2, &pkg3}))
37
+ })
38
+
39
+ It("returns packages in resolved order with multiple deps", func() {
40
+ pkg1 := Package{Name: "fake-package-name-1"}
41
+ pkg2 := Package{Name: "fake-package-name-2"}
42
+
43
+ pkg3 := Package{
44
+ Name: "fake-package-name-3",
45
+ Dependencies: []*Package{&pkg1, &pkg2},
46
+ }
47
+
48
+ release.Packages = []*Package{&pkg3, &pkg2, &pkg1}
49
+
50
+ pkgs := release.ResolvedPackageDependencies()
51
+ Expect(pkgs).To(Equal([]*Package{&pkg2, &pkg1, &pkg3})) // or pkg1, pkg2, pkg3
52
+ })
53
+
54
+ It("compiles BOSH release packages (example)", func() {
55
+ nginx := Package{Name: "nginx"}
56
+ genisoimage := Package{Name: "genisoimage"}
57
+ powerdns := Package{Name: "powerdns"}
58
+ ruby := Package{Name: "ruby"}
59
+
60
+ blobstore := Package{
61
+ Name: "blobstore",
62
+ Dependencies: []*Package{&ruby},
63
+ }
64
+
65
+ mysql := Package{Name: "mysql"}
66
+
67
+ nats := Package{
68
+ Name: "nats",
69
+ Dependencies: []*Package{&ruby},
70
+ }
71
+
72
+ common := Package{Name: "common"}
73
+ redis := Package{Name: "redis"}
74
+ libpq := Package{Name: "libpq"}
75
+ postgres := Package{Name: "postgres"}
76
+
77
+ registry := Package{
78
+ Name: "registry",
79
+ Dependencies: []*Package{&libpq, &mysql, &ruby},
80
+ }
81
+
82
+ director := Package{
83
+ Name: "director",
84
+ Dependencies: []*Package{&libpq, &mysql, &ruby},
85
+ }
86
+
87
+ healthMonitor := Package{
88
+ Name: "health_monitor",
89
+ Dependencies: []*Package{&ruby},
90
+ }
91
+
92
+ release.Packages = []*Package{
93
+ &nginx,
94
+ &genisoimage,
95
+ &powerdns,
96
+ &blobstore, // before ruby
97
+ &ruby,
98
+ &mysql,
99
+ &nats,
100
+ &common,
101
+ &director, // before libpq, postgres; after ruby
102
+ &redis,
103
+ &registry, // before libpq, postgres; after ruby
104
+ &libpq,
105
+ &postgres,
106
+ &healthMonitor, // after ruby, libpq, postgres
107
+ }
108
+
109
+ pkgs := release.ResolvedPackageDependencies()
110
+
111
+ Expect(pkgs).To(Equal([]*Package{
112
+ &nginx,
113
+ &genisoimage,
114
+ &powerdns,
115
+ &ruby,
116
+ &mysql,
117
+ &nats,
118
+ &common,
119
+ &redis,
120
+ &libpq,
121
+ &postgres,
122
+ &healthMonitor, // currently always appended to the end
123
+ &blobstore,
124
+ &director,
125
+ &registry,
126
+ }))
127
+ })
128
+ })
129
+ })
@@ -0,0 +1,139 @@
1
+ package release
2
+
3
+ import (
4
+ "path/filepath"
5
+
6
+ bosherr "bosh/errors"
7
+ boshlog "bosh/logger"
8
+ boshsys "bosh/system"
9
+
10
+ bpdload "boshprovisioner/downloader"
11
+ bprelman "boshprovisioner/release/manifest"
12
+ bptar "boshprovisioner/tar"
13
+ )
14
+
15
+ const tarReaderLogTag = "TarReader"
16
+
17
+ // TarReader reads .tgz release file and returns a Release.
18
+ // See unpacked release directory layout at the end of the file.
19
+ type TarReader struct {
20
+ path string
21
+ downloader bpdload.Downloader
22
+ extractor bptar.Extractor
23
+ fs boshsys.FileSystem
24
+ logger boshlog.Logger
25
+
26
+ // location to clean if successfully downloaded/extracted
27
+ downloadPath string
28
+ extractPath string
29
+ }
30
+
31
+ func NewTarReader(
32
+ path string,
33
+ downloader bpdload.Downloader,
34
+ extractor bptar.Extractor,
35
+ fs boshsys.FileSystem,
36
+ logger boshlog.Logger,
37
+ ) *TarReader {
38
+ return &TarReader{
39
+ path: path,
40
+ downloader: downloader,
41
+ extractor: extractor,
42
+ fs: fs,
43
+ logger: logger,
44
+ }
45
+ }
46
+
47
+ func (tr *TarReader) Read() (Release, error) {
48
+ var release Release
49
+
50
+ downloadPath, err := tr.downloader.Download(tr.path)
51
+ if err != nil {
52
+ return release, bosherr.WrapError(err, "Downloading release")
53
+ }
54
+
55
+ tr.downloadPath = downloadPath
56
+
57
+ extractPath, err := tr.extractor.Extract(tr.downloadPath)
58
+ if err != nil {
59
+ cleanUpErr := tr.downloader.CleanUp(tr.downloadPath)
60
+ if cleanUpErr != nil {
61
+ tr.logger.Debug(tarReaderLogTag,
62
+ "Failed to clean up downloaded release %v", cleanUpErr)
63
+ }
64
+
65
+ return release, bosherr.WrapError(err, "Extracting release")
66
+ }
67
+
68
+ tr.extractPath = extractPath
69
+
70
+ manifestPath := filepath.Join(tr.extractPath, "release.MF")
71
+
72
+ manifest, err := bprelman.NewManifestFromPath(manifestPath, tr.fs)
73
+ if err != nil {
74
+ closeErr := tr.Close()
75
+ if closeErr != nil {
76
+ tr.logger.Debug(tarReaderLogTag,
77
+ "Failed to close release %v", closeErr)
78
+ }
79
+
80
+ return release, bosherr.WrapError(err, "Building manifest")
81
+ }
82
+
83
+ tr.logger.Debug(tarReaderLogTag, "Done building manifest %#v", manifest)
84
+
85
+ release.populateFromManifest(manifest)
86
+
87
+ tr.populateReleaseTarPaths(&release)
88
+
89
+ return release, nil
90
+ }
91
+
92
+ func (tr TarReader) Close() error {
93
+ dlErr := tr.downloader.CleanUp(tr.downloadPath)
94
+ if dlErr != nil {
95
+ tr.logger.Debug(tarReaderLogTag,
96
+ "Failed to clean up downloaded release %v", dlErr)
97
+ }
98
+
99
+ exErr := tr.extractor.CleanUp(tr.extractPath)
100
+ if exErr != nil {
101
+ tr.logger.Debug(tarReaderLogTag,
102
+ "Failed to clean up extracted release %v", exErr)
103
+ }
104
+
105
+ if dlErr != nil {
106
+ return dlErr
107
+ }
108
+
109
+ return exErr
110
+ }
111
+
112
+ // populateReleaseTarPaths sets TarPath for each job/package in the release.
113
+ func (tr TarReader) populateReleaseTarPaths(release *Release) {
114
+ for i, job := range release.Jobs {
115
+ fileName := job.Name + ".tgz"
116
+ release.Jobs[i].TarPath = filepath.Join(tr.extractPath, "jobs", fileName)
117
+ }
118
+
119
+ for _, pkg := range release.Packages {
120
+ fileName := pkg.Name + ".tgz"
121
+ pkg.TarPath = filepath.Join(tr.extractPath, "packages", fileName)
122
+ }
123
+ }
124
+
125
+ /*
126
+ Example layout of an unpackaged release tar:
127
+
128
+ $ tree ~/Downloads/dummy-release
129
+ ~/Downloads/dummy-release
130
+ ├── jobs
131
+ │   ├── dummy.tgz
132
+ │   ├── dummy_with_bad_package.tgz
133
+ │   ├── dummy_with_package.tgz
134
+ │   └── dummy_with_properties.tgz
135
+ ├── packages
136
+ │   ├── bad_package.tgz
137
+ │   └── dummy_package.tgz
138
+ └── release.MF
139
+ */
@@ -0,0 +1,114 @@
1
+ package releasesrepo
2
+
3
+ import (
4
+ boshblob "bosh/blobstore"
5
+ bosherr "bosh/errors"
6
+ boshlog "bosh/logger"
7
+
8
+ bpdep "boshprovisioner/deployment"
9
+ bpdload "boshprovisioner/downloader"
10
+ bpindex "boshprovisioner/index"
11
+ )
12
+
13
+ type BlobstoreReleasesRepository struct {
14
+ downloader bpdload.Downloader
15
+ blobstore boshblob.Blobstore
16
+ index bpindex.Index
17
+ logger boshlog.Logger
18
+ }
19
+
20
+ type blobstoreRecord struct {
21
+ BlobID string
22
+ Fingerprint string
23
+ }
24
+
25
+ func NewBlobstoreReleasesRepository(
26
+ downloader bpdload.Downloader,
27
+ blobstore boshblob.Blobstore,
28
+ index bpindex.Index,
29
+ logger boshlog.Logger,
30
+ ) BlobstoreReleasesRepository {
31
+ return BlobstoreReleasesRepository{
32
+ downloader: downloader,
33
+ blobstore: blobstore,
34
+ index: index,
35
+ logger: logger,
36
+ }
37
+ }
38
+
39
+ func (rr BlobstoreReleasesRepository) Pull(release bpdep.Release) error {
40
+ var record blobstoreRecord
41
+
42
+ err := rr.index.Find(release, &record)
43
+ if err == nil {
44
+ return nil // nothing to do if already exists
45
+ } else if err != bpindex.ErrNotFound {
46
+ return bosherr.WrapError(err, "Finding release in index")
47
+ }
48
+
49
+ path, err := rr.downloader.Download(release.URL)
50
+ if err != nil {
51
+ return bosherr.WrapError(err, "Downloading release")
52
+ }
53
+
54
+ defer rr.downloader.CleanUp(path)
55
+
56
+ blobID, fingerprint, err := rr.blobstore.Create(path)
57
+ if err != nil {
58
+ return bosherr.WrapError(err, "Creating release blob")
59
+ }
60
+
61
+ record = blobstoreRecord{
62
+ BlobID: blobID,
63
+ Fingerprint: fingerprint,
64
+ }
65
+
66
+ err = rr.index.Save(release, record)
67
+ if err != nil {
68
+ // todo delete from blobstore
69
+
70
+ return bosherr.WrapError(err, "Saving release to index")
71
+ }
72
+
73
+ return nil
74
+ }
75
+
76
+ func (rr BlobstoreReleasesRepository) KeepOnly(releasesToKeep []bpdep.Release) error {
77
+ var allReleases []bpdep.Release
78
+
79
+ err := rr.index.ListKeys(&allReleases)
80
+ if err != nil {
81
+ return bosherr.WrapError(err, "Listing releases in index")
82
+ }
83
+
84
+ for _, foundRelease := range allReleases {
85
+ var keep bool
86
+
87
+ for _, releaseToKeep := range releasesToKeep {
88
+ if foundRelease == releaseToKeep {
89
+ keep = true
90
+ break
91
+ }
92
+ }
93
+
94
+ if keep {
95
+ continue
96
+ }
97
+
98
+ var record blobstoreRecord
99
+
100
+ err := rr.index.Find(foundRelease, &record)
101
+ if err != nil {
102
+ return bosherr.WrapError(err, "Finding release to delete")
103
+ }
104
+
105
+ // todo delete from blobstore
106
+
107
+ err = rr.index.Remove(foundRelease)
108
+ if err != nil {
109
+ return bosherr.WrapError(err, "Deleting release from index")
110
+ }
111
+ }
112
+
113
+ return nil
114
+ }
@@ -0,0 +1,15 @@
1
+ package releasesrepo
2
+
3
+ import (
4
+ bpdep "boshprovisioner/deployment"
5
+ )
6
+
7
+ // ReleasesRepository manages collection of releases
8
+ // available to use for provisioning
9
+ type ReleasesRepository interface {
10
+ // Pull downloads/copies/retrieves a release
11
+ Pull(bpdep.Release) error
12
+
13
+ // KeepOnly deletes all releases but the provided ones
14
+ KeepOnly([]bpdep.Release) error
15
+ }
@@ -0,0 +1,68 @@
1
+ package tar
2
+
3
+ import (
4
+ bosherr "bosh/errors"
5
+ boshlog "bosh/logger"
6
+ boshsys "bosh/system"
7
+ )
8
+
9
+ const cmdCompressorLogTag = "CmdCompressor"
10
+
11
+ type CmdCompressor struct {
12
+ runner boshsys.CmdRunner
13
+ fs boshsys.FileSystem
14
+ logger boshlog.Logger
15
+ }
16
+
17
+ func NewCmdCompressor(
18
+ runner boshsys.CmdRunner,
19
+ fs boshsys.FileSystem,
20
+ logger boshlog.Logger,
21
+ ) CmdCompressor {
22
+ return CmdCompressor{
23
+ runner: runner,
24
+ fs: fs,
25
+ logger: logger,
26
+ }
27
+ }
28
+
29
+ func (c CmdCompressor) Compress(path string) (string, error) {
30
+ compressPath, err := c.tmpPath()
31
+ if err != nil {
32
+ return "", err
33
+ }
34
+
35
+ c.logger.Debug(cmdCompressorLogTag, "Compressing %s to %s", path, compressPath)
36
+
37
+ _, _, _, err = c.runner.RunCommand("tar", "-C", path, "-czf", compressPath, ".")
38
+ if err != nil {
39
+ return "", bosherr.WrapError(err, "Running tar")
40
+ }
41
+
42
+ return compressPath, nil
43
+ }
44
+
45
+ func (c CmdCompressor) CleanUp(path string) error {
46
+ return c.fs.RemoveAll(path)
47
+ }
48
+
49
+ func (c CmdCompressor) tmpPath() (string, error) {
50
+ file, err := c.fs.TempFile("tar-CmdCompressor")
51
+ if err != nil {
52
+ return "", bosherr.WrapError(err, "Creating extract destination")
53
+ }
54
+
55
+ compressPath := file.Name()
56
+
57
+ err = file.Close()
58
+ if err != nil {
59
+ return "", bosherr.WrapError(err, "Closing temp file")
60
+ }
61
+
62
+ err = c.fs.RemoveAll(compressPath)
63
+ if err != nil {
64
+ return "", bosherr.WrapError(err, "Remove temp file")
65
+ }
66
+
67
+ return compressPath, nil
68
+ }
@@ -0,0 +1,47 @@
1
+ package tar
2
+
3
+ import (
4
+ bosherr "bosh/errors"
5
+ boshlog "bosh/logger"
6
+ boshsys "bosh/system"
7
+ )
8
+
9
+ const cmdExtractorLogTag = "CmdExtractor"
10
+
11
+ type CmdExtractor struct {
12
+ runner boshsys.CmdRunner
13
+ fs boshsys.FileSystem
14
+ logger boshlog.Logger
15
+ }
16
+
17
+ func NewCmdExtractor(
18
+ runner boshsys.CmdRunner,
19
+ fs boshsys.FileSystem,
20
+ logger boshlog.Logger,
21
+ ) CmdExtractor {
22
+ return CmdExtractor{
23
+ runner: runner,
24
+ fs: fs,
25
+ logger: logger,
26
+ }
27
+ }
28
+
29
+ func (e CmdExtractor) Extract(path string) (string, error) {
30
+ extractPath, err := e.fs.TempDir("tar-CmdExtractor")
31
+ if err != nil {
32
+ return "", bosherr.WrapError(err, "Creating extract destination")
33
+ }
34
+
35
+ e.logger.Debug(cmdExtractorLogTag, "Extract tar %s to %s", path, extractPath)
36
+
37
+ _, _, _, err = e.runner.RunCommand("tar", "-C", extractPath, "-xzf", path)
38
+ if err != nil {
39
+ return "", bosherr.WrapError(err, "Running tar")
40
+ }
41
+
42
+ return extractPath, nil
43
+ }
44
+
45
+ func (e CmdExtractor) CleanUp(path string) error {
46
+ return e.fs.RemoveAll(path)
47
+ }
@@ -0,0 +1,6 @@
1
+ package tar
2
+
3
+ type Compressor interface {
4
+ Compress(string) (string, error)
5
+ CleanUp(string) error
6
+ }