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,111 @@
1
+ package deployment
2
+
3
+ import (
4
+ bosherr "bosh/errors"
5
+ )
6
+
7
+ // SemanticValidator validates deployment to determine if it represents a meaningful state.
8
+ // e.g. - is each job template associated with a release?
9
+ // - are there enough static ips for each job instance?
10
+ type SemanticValidator struct {
11
+ deployment Deployment
12
+ }
13
+
14
+ func NewSemanticValidator(deployment Deployment) SemanticValidator {
15
+ return SemanticValidator{deployment: deployment}
16
+ }
17
+
18
+ func (v SemanticValidator) Validate() error {
19
+ for _, net := range v.deployment.Networks {
20
+ err := v.validateNetwork(net)
21
+ if err != nil {
22
+ return bosherr.WrapError(err, "Network %s", net.Name)
23
+ }
24
+ }
25
+
26
+ for _, release := range v.deployment.Releases {
27
+ err := v.validateRelease(release)
28
+ if err != nil {
29
+ return bosherr.WrapError(err, "Release %s", release.Name)
30
+ }
31
+ }
32
+
33
+ err := v.validateInstance(v.deployment.CompilationInstance)
34
+ if err != nil {
35
+ return bosherr.WrapError(err, "Compilation instance")
36
+ }
37
+
38
+ for _, job := range v.deployment.Jobs {
39
+ err := v.validateJob(job)
40
+ if err != nil {
41
+ return bosherr.WrapError(err, "Job %s", job.Name)
42
+ }
43
+ }
44
+
45
+ return nil
46
+ }
47
+
48
+ func (v SemanticValidator) validateNetwork(network Network) error {
49
+ if network.Type == NetworkTypeManual {
50
+ return bosherr.New("Manual networking is not supported")
51
+ }
52
+
53
+ return nil
54
+ }
55
+
56
+ func (v SemanticValidator) validateRelease(release Release) error {
57
+ if release.Version == "latest" {
58
+ return bosherr.New("Version 'latest' is not supported")
59
+ }
60
+
61
+ return nil
62
+ }
63
+
64
+ func (v SemanticValidator) validateJob(job Job) error {
65
+ for _, template := range job.Templates {
66
+ err := v.validateTemplate(template)
67
+ if err != nil {
68
+ return bosherr.WrapError(err, "Template %s", template.Name)
69
+ }
70
+ }
71
+
72
+ for _, instance := range job.Instances {
73
+ err := v.validateInstance(instance)
74
+ if err != nil {
75
+ return bosherr.WrapError(err, "Instance %d", instance.Index)
76
+ }
77
+ }
78
+
79
+ return nil
80
+ }
81
+
82
+ func (v SemanticValidator) validateTemplate(template Template) error {
83
+ if template.Release == nil {
84
+ return bosherr.New("Missing associated release")
85
+ }
86
+
87
+ return nil
88
+ }
89
+
90
+ func (v SemanticValidator) validateInstance(instance Instance) error {
91
+ for i, na := range instance.NetworkAssociations {
92
+ err := v.validateNetworkAssociation(na)
93
+ if err != nil {
94
+ return bosherr.WrapError(err, "Network association %d", i)
95
+ }
96
+ }
97
+
98
+ return nil
99
+ }
100
+
101
+ func (v SemanticValidator) validateNetworkAssociation(na NetworkAssociation) error {
102
+ if na.Network == nil {
103
+ return bosherr.New("Missing associated network")
104
+ }
105
+
106
+ if na.MustHaveStaticIP && na.StaticIP == nil {
107
+ return bosherr.New("Missing static IP assignment")
108
+ }
109
+
110
+ return nil
111
+ }
@@ -0,0 +1,55 @@
1
+ package downloader
2
+
3
+ import (
4
+ gourl "net/url"
5
+
6
+ boshblob "bosh/blobstore"
7
+ bosherr "bosh/errors"
8
+ boshlog "bosh/logger"
9
+ )
10
+
11
+ const blobstoreDownloaderLogTag = "BlobstoreDownloader"
12
+
13
+ type BlobstoreDownloader struct {
14
+ blobstore boshblob.Blobstore
15
+ logger boshlog.Logger
16
+ }
17
+
18
+ func NewBlobstoreDownloader(
19
+ blobstore boshblob.Blobstore,
20
+ logger boshlog.Logger,
21
+ ) BlobstoreDownloader {
22
+ return BlobstoreDownloader{
23
+ blobstore: blobstore,
24
+ logger: logger,
25
+ }
26
+ }
27
+
28
+ // Download takes URL of format blobstore:///blobId?fingerprint=sha1-value
29
+ func (d BlobstoreDownloader) Download(url string) (string, error) {
30
+ parsedURL, err := gourl.Parse(url)
31
+ if err != nil {
32
+ return "", bosherr.WrapError(err, "Parsing url %s", url)
33
+ }
34
+
35
+ var fingerprint string
36
+
37
+ if fingerprints, found := parsedURL.Query()["fingerprint"]; found {
38
+ if len(fingerprints) > 0 {
39
+ fingerprint = fingerprints[0]
40
+ }
41
+ }
42
+
43
+ path, err := d.blobstore.Get(parsedURL.Path, fingerprint)
44
+ if err != nil {
45
+ return "", bosherr.WrapError(err, "Downloading blob")
46
+ }
47
+
48
+ d.logger.Debug(blobstoreDownloaderLogTag, "Downloaded %s to %s", url, path)
49
+
50
+ return path, nil
51
+ }
52
+
53
+ func (d BlobstoreDownloader) CleanUp(path string) error {
54
+ return d.blobstore.CleanUp(path)
55
+ }
@@ -0,0 +1,22 @@
1
+ package downloader
2
+
3
+ import (
4
+ boshblob "bosh/blobstore"
5
+ boshlog "bosh/logger"
6
+ boshsys "bosh/system"
7
+ )
8
+
9
+ func NewDefaultMuxDownloader(
10
+ blobstore boshblob.Blobstore,
11
+ fs boshsys.FileSystem,
12
+ logger boshlog.Logger,
13
+ ) MuxDownloader {
14
+ mux := map[string]Downloader{
15
+ "http": NewHTTPDownloader(fs, logger),
16
+ "https": NewHTTPDownloader(fs, logger),
17
+ "file": NewLocalFSDownloader(fs, logger),
18
+ "blobstore": NewBlobstoreDownloader(blobstore, logger),
19
+ }
20
+
21
+ return NewMuxDownloader(mux, logger)
22
+ }
@@ -0,0 +1,6 @@
1
+ package downloader
2
+
3
+ type Downloader interface {
4
+ Download(string) (string, error)
5
+ CleanUp(string) error
6
+ }
@@ -0,0 +1,53 @@
1
+ package downloader
2
+
3
+ import (
4
+ "io"
5
+ "net/http"
6
+
7
+ bosherr "bosh/errors"
8
+ boshlog "bosh/logger"
9
+ boshsys "bosh/system"
10
+ )
11
+
12
+ const httpDownloaderLogTag = "HTTPDownloader"
13
+
14
+ type HTTPDownloader struct {
15
+ fs boshsys.FileSystem
16
+ logger boshlog.Logger
17
+ }
18
+
19
+ func NewHTTPDownloader(
20
+ fs boshsys.FileSystem,
21
+ logger boshlog.Logger,
22
+ ) HTTPDownloader {
23
+ return HTTPDownloader{fs: fs, logger: logger}
24
+ }
25
+
26
+ func (d HTTPDownloader) Download(url string) (string, error) {
27
+ file, err := d.fs.TempFile("release-Downloader-HTTPDownloader")
28
+ if err != nil {
29
+ return "", bosherr.WrapError(err, "Creating download destination")
30
+ }
31
+
32
+ d.logger.Debug(httpDownloaderLogTag, "Downloaded %s to %s", url, file.Name())
33
+
34
+ defer file.Close()
35
+
36
+ resp, err := http.Get(url)
37
+ if err != nil {
38
+ return "", bosherr.WrapError(err, "Get url")
39
+ }
40
+
41
+ defer resp.Body.Close()
42
+
43
+ _, err = io.Copy(file, resp.Body)
44
+ if err != nil {
45
+ return "", bosherr.WrapError(err, "Copying response to file")
46
+ }
47
+
48
+ return file.Name(), nil
49
+ }
50
+
51
+ func (d HTTPDownloader) CleanUp(path string) error {
52
+ return d.fs.RemoveAll(path)
53
+ }
@@ -0,0 +1,48 @@
1
+ package downloader
2
+
3
+ import (
4
+ "strings"
5
+
6
+ bosherr "bosh/errors"
7
+ boshlog "bosh/logger"
8
+ boshsys "bosh/system"
9
+ )
10
+
11
+ const localFSDownloaderLogTag = "Downloader"
12
+
13
+ type LocalFSDownloader struct {
14
+ fs boshsys.FileSystem
15
+ logger boshlog.Logger
16
+ }
17
+
18
+ func NewLocalFSDownloader(
19
+ fs boshsys.FileSystem,
20
+ logger boshlog.Logger,
21
+ ) LocalFSDownloader {
22
+ return LocalFSDownloader{fs: fs, logger: logger}
23
+ }
24
+
25
+ func (d LocalFSDownloader) Download(url string) (string, error) {
26
+ file, err := d.fs.TempFile("downloader-LocalFSDownloader")
27
+ if err != nil {
28
+ return "", bosherr.WrapError(err, "Creating download destination")
29
+ }
30
+
31
+ d.logger.Debug(localFSDownloaderLogTag, "Downloaded %s to %s", url, file.Name())
32
+
33
+ err = file.Close()
34
+ if err != nil {
35
+ return "", bosherr.WrapError(err, "Closing download destination")
36
+ }
37
+
38
+ err = d.fs.CopyFile(strings.TrimPrefix(url, "file://"), file.Name())
39
+ if err != nil {
40
+ return "", bosherr.WrapError(err, "Copying to destination")
41
+ }
42
+
43
+ return file.Name(), nil
44
+ }
45
+
46
+ func (d LocalFSDownloader) CleanUp(path string) error {
47
+ return d.fs.RemoveAll(path)
48
+ }
@@ -0,0 +1,69 @@
1
+ package downloader
2
+
3
+ import (
4
+ "strings"
5
+
6
+ bosherr "bosh/errors"
7
+ boshlog "bosh/logger"
8
+ )
9
+
10
+ const muxDownloaderLogTag = "Downloader"
11
+
12
+ type MuxDownloader struct {
13
+ // e.g. {"http": NewHTTPDownloader()}
14
+ mux map[string]Downloader
15
+
16
+ logger boshlog.Logger
17
+
18
+ // Track which Downloader should be used to clean up
19
+ downloadedPaths map[string]Downloader
20
+ }
21
+
22
+ func NewMuxDownloader(
23
+ mux map[string]Downloader,
24
+ logger boshlog.Logger,
25
+ ) MuxDownloader {
26
+ return MuxDownloader{
27
+ mux: mux,
28
+ logger: logger,
29
+
30
+ downloadedPaths: map[string]Downloader{},
31
+ }
32
+ }
33
+
34
+ func (d MuxDownloader) Download(url string) (string, error) {
35
+ for prefix, downloader := range d.mux {
36
+ if strings.HasPrefix(url, prefix+"://") {
37
+ path, err := downloader.Download(url)
38
+ if err != nil {
39
+ return path, err
40
+ }
41
+
42
+ // Only remember path if Downloader succeeded
43
+ d.downloadedPaths[path] = downloader
44
+
45
+ return path, err
46
+ }
47
+ }
48
+
49
+ return "", bosherr.New("URL %s without matching downloader", url)
50
+ }
51
+
52
+ func (d MuxDownloader) CleanUp(path string) error {
53
+ downloader, ok := d.downloadedPaths[path]
54
+ if !ok {
55
+ // programmer error
56
+ return bosherr.New("Unknown path %s requested to be cleaned up", path)
57
+ }
58
+
59
+ err := downloader.CleanUp(path)
60
+ if err != nil {
61
+ return err
62
+ }
63
+
64
+ // Forget path only if associated Downloader succeeded cleaning up
65
+ // so that CleanUp could be called multiple times
66
+ delete(d.downloadedPaths, path)
67
+
68
+ return nil
69
+ }
@@ -0,0 +1,72 @@
1
+ package eventlog
2
+
3
+ import (
4
+ "encoding/json"
5
+ "io"
6
+ "os"
7
+
8
+ bosherr "bosh/errors"
9
+ boshlog "bosh/logger"
10
+ )
11
+
12
+ const logLogTag = "Log"
13
+
14
+ type Log struct {
15
+ writer io.Writer
16
+ logger boshlog.Logger
17
+ }
18
+
19
+ type logEntry struct {
20
+ Time int64 `json:"time"`
21
+
22
+ Stage string `json:"stage"`
23
+ Task string `json:"task"`
24
+ Tags []string `json:"tags"`
25
+
26
+ Total int `json:"total"`
27
+ Index int `json:"index"`
28
+
29
+ State string `json:"state"`
30
+ Progress int `json:"progress"`
31
+
32
+ // Might contain error key
33
+ Data map[string]interface{} `json:"data,omitempty"`
34
+ }
35
+
36
+ func NewLog(logger boshlog.Logger) Log {
37
+ return Log{
38
+ writer: os.Stdout,
39
+ logger: logger,
40
+ }
41
+ }
42
+
43
+ func (l Log) BeginStage(name string, total int) *Stage {
44
+ return &Stage{
45
+ log: l,
46
+ name: name,
47
+ total: total,
48
+ }
49
+ }
50
+
51
+ func (l Log) writeLogEntryNoErr(entry logEntry) {
52
+ err := l.writeLogEntry(entry)
53
+ if err != nil {
54
+ l.logger.Error(logLogTag, "Failed writing log entry %s", err.Error())
55
+ }
56
+ }
57
+
58
+ func (l Log) writeLogEntry(entry logEntry) error {
59
+ bytes, err := json.Marshal(entry)
60
+ if err != nil {
61
+ return bosherr.WrapError(err, "Marshalling log entry")
62
+ }
63
+
64
+ bytes = append(bytes, []byte("\n")...)
65
+
66
+ _, err = l.writer.Write(bytes)
67
+ if err != nil {
68
+ return bosherr.WrapError(err, "Writing log entry")
69
+ }
70
+
71
+ return nil
72
+ }
@@ -0,0 +1,39 @@
1
+ package eventlog
2
+
3
+ import (
4
+ "sync"
5
+ )
6
+
7
+ type Stage struct {
8
+ log Log
9
+
10
+ name string
11
+
12
+ total int
13
+ currTaskIndex int
14
+
15
+ indexLock sync.Mutex
16
+ }
17
+
18
+ func (s *Stage) BeginTask(name string) Task {
19
+ s.indexLock.Lock()
20
+
21
+ index := s.currTaskIndex
22
+ s.currTaskIndex++
23
+
24
+ s.indexLock.Unlock()
25
+
26
+ task := Task{
27
+ log: s.log,
28
+
29
+ stageName: s.name,
30
+ name: name,
31
+
32
+ total: s.total,
33
+ index: index,
34
+ }
35
+
36
+ task.Start()
37
+
38
+ return task
39
+ }
@@ -0,0 +1,58 @@
1
+ package eventlog
2
+
3
+ import (
4
+ "time"
5
+ )
6
+
7
+ type Task struct {
8
+ log Log
9
+
10
+ stageName string
11
+ name string
12
+
13
+ total int
14
+ index int
15
+ }
16
+
17
+ func (t Task) Start() {
18
+ entry := logEntry{
19
+ Time: time.Now().Unix(),
20
+
21
+ Stage: t.stageName,
22
+ Task: t.name,
23
+
24
+ Total: t.total,
25
+ Index: t.index,
26
+
27
+ State: "started",
28
+ Progress: 0,
29
+ }
30
+
31
+ t.log.writeLogEntryNoErr(entry)
32
+ }
33
+
34
+ func (t Task) End(err error) error {
35
+ entry := logEntry{
36
+ Time: time.Now().Unix(),
37
+
38
+ Stage: t.stageName,
39
+ Task: t.name,
40
+
41
+ Total: t.total,
42
+ Index: t.index,
43
+
44
+ State: "finished",
45
+ Progress: 100,
46
+ }
47
+
48
+ if err != nil {
49
+ entry.State = "failed"
50
+ entry.Data = map[string]interface{}{
51
+ "error": err.Error(),
52
+ }
53
+ }
54
+
55
+ t.log.writeLogEntryNoErr(entry)
56
+
57
+ return err
58
+ }