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