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,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
+ }