bosh-workspace 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/.ruby-version +1 -1
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/Guardfile +2 -2
- data/README.md +78 -39
- data/Rakefile +4 -0
- data/bosh-workspace.gemspec +4 -1
- data/lib/bosh/cli/commands/prepare.rb +74 -0
- data/lib/bosh/cli/commands/{01_make_manifest.rb → project_deployment.rb} +4 -26
- data/lib/bosh/workspace.rb +7 -3
- data/lib/bosh/workspace/helpers/dns_helper.rb +72 -0
- data/lib/bosh/workspace/helpers/project_deployment_helper.rb +8 -3
- data/lib/bosh/workspace/helpers/release_helper.rb +33 -0
- data/lib/bosh/workspace/helpers/spiff_helper.rb +1 -1
- data/lib/bosh/workspace/helpers/stemcell_helper.rb +45 -0
- data/lib/bosh/workspace/manifest_builder.rb +10 -25
- data/lib/bosh/workspace/project_deployment.rb +77 -0
- data/lib/bosh/workspace/release.rb +41 -33
- data/lib/bosh/workspace/stemcell.rb +23 -0
- data/lib/bosh/workspace/stub_file.rb +44 -0
- data/lib/bosh/workspace/version.rb +1 -1
- data/spec/assets/dns/job-properties.yml +22 -0
- data/spec/assets/dns/jobs.yml +18 -0
- data/spec/assets/dns/networks-manual.yml +19 -0
- data/spec/assets/dns/networks-no-manual.yml +18 -0
- data/spec/assets/dns/properties.yml +29 -0
- data/spec/assets/foo-boshrelease-repo.zip +0 -0
- data/spec/commands/prepare_spec.rb +99 -0
- data/spec/commands/{command_make_manifest_spec.rb → project_deployment_spec.rb} +4 -23
- data/spec/helpers/dns_helper_spec.rb +59 -0
- data/spec/helpers/project_deployment_helper_spec.rb +24 -23
- data/spec/helpers/release_helper_spec.rb +76 -0
- data/spec/helpers/spiff_helper_spec.rb +2 -2
- data/spec/helpers/stemcell_helper_spec.rb +89 -0
- data/spec/manifest_builder_spec.rb +24 -45
- data/spec/project_deployment_spec.rb +157 -0
- data/spec/release_spec.rb +39 -18
- data/spec/spec_helper.rb +9 -3
- data/spec/stemcell_spec.rb +28 -0
- data/spec/stub_file_spec.rb +74 -0
- metadata +90 -22
- data/lib/bosh/workspace/deployment_manifest.rb +0 -67
- data/lib/bosh/workspace/release_manager.rb +0 -14
- data/spec/deployment_manifest_spec.rb +0 -93
- data/spec/release_manager_spec.rb +0 -17
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bosh::Workspace
|
2
|
+
module ReleaseHelper
|
3
|
+
include ProjectDeploymentHelper
|
4
|
+
|
5
|
+
def release_uploaded?(name, version)
|
6
|
+
remote_release = director.get_release(name) rescue nil
|
7
|
+
remote_release && remote_release["versions"].include?(version.to_s)
|
8
|
+
end
|
9
|
+
|
10
|
+
def release_upload(manifest_file)
|
11
|
+
release_cmd.upload(manifest_file)
|
12
|
+
end
|
13
|
+
|
14
|
+
def releases_dir
|
15
|
+
@releases_dir ||= begin
|
16
|
+
FileUtils.mkdir_p(File.join(work_dir, ".releases")).first
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def project_deployment_releases
|
21
|
+
@releases ||= begin
|
22
|
+
project_deployment.releases.map { |r| Release.new(r, releases_dir) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def release_cmd
|
29
|
+
@release_cmd ||= Bosh::Cli::Command::Release.new
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Bosh::Workspace
|
2
|
+
module StemcellHelper
|
3
|
+
include ProjectDeploymentHelper
|
4
|
+
|
5
|
+
def stemcell_download(stemcell_name)
|
6
|
+
Dir.chdir(stemcells_dir) do
|
7
|
+
say "Downloading stemcell '#{stemcell_name}'"
|
8
|
+
nl
|
9
|
+
stemcell_cmd.download_public(stemcell_name)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def stemcell_upload(stemcell_file)
|
14
|
+
say "Uploading stemcell '#{File.basename(stemcell_file)}'"
|
15
|
+
nl
|
16
|
+
stemcell_cmd.upload(stemcell_file)
|
17
|
+
end
|
18
|
+
|
19
|
+
def stemcell_uploaded?(name, version)
|
20
|
+
existing = director.list_stemcells.select do |sc|
|
21
|
+
sc['name'] == name && sc['version'] == version.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
!existing.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def stemcells_dir
|
28
|
+
@stemcells_dir ||= begin
|
29
|
+
FileUtils.mkdir_p(File.join(work_dir, ".stemcells")).first
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def project_deployment_stemcells
|
34
|
+
@stemcells ||= begin
|
35
|
+
project_deployment.stemcells.map { |s| Stemcell.new(s, stemcells_dir) }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def stemcell_cmd
|
42
|
+
@stemcell_cmd ||= Bosh::Cli::Command::Stemcell.new
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
|
-
module Bosh::
|
1
|
+
module Bosh::Workspace
|
2
2
|
class ManifestBuilder
|
3
|
-
include Bosh::
|
3
|
+
include Bosh::Workspace::SpiffHelper
|
4
4
|
|
5
|
-
def self.build(
|
6
|
-
manifest_builder = ManifestBuilder.new(
|
5
|
+
def self.build(project_deployment, work_dir)
|
6
|
+
manifest_builder = ManifestBuilder.new(project_deployment, work_dir)
|
7
7
|
manifest_builder.merge_templates
|
8
8
|
end
|
9
9
|
|
10
|
-
def initialize(
|
11
|
-
@
|
10
|
+
def initialize(project_deployment, work_dir)
|
11
|
+
@project_deployment = project_deployment
|
12
12
|
@work_dir = work_dir
|
13
13
|
end
|
14
14
|
|
15
15
|
def merge_templates
|
16
|
-
spiff_merge spiff_template_paths, @
|
16
|
+
spiff_merge spiff_template_paths, @project_deployment.merged_file
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
@@ -24,32 +24,17 @@ module Bosh::Manifests
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def template_paths
|
27
|
-
@
|
27
|
+
@project_deployment.templates.map { |t| template_path(t) }
|
28
28
|
end
|
29
29
|
|
30
30
|
def stub_file_path
|
31
31
|
path = hidden_file_path(:stubs)
|
32
|
-
|
32
|
+
StubFile.create(path, @project_deployment)
|
33
33
|
path
|
34
34
|
end
|
35
35
|
|
36
|
-
def stub_file_content
|
37
|
-
{
|
38
|
-
"director_uuid" => @manifest.director_uuid,
|
39
|
-
"releases" => filterd_releases,
|
40
|
-
"meta" => @manifest.meta
|
41
|
-
}.to_yaml
|
42
|
-
end
|
43
|
-
|
44
|
-
def filterd_releases
|
45
|
-
allowed_keys = %w[name version]
|
46
|
-
@manifest.releases.map do |release|
|
47
|
-
release.select { |key| allowed_keys.include?(key) }
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
36
|
def hidden_file_path(type)
|
52
|
-
File.join(hidden_dir_path(type), "#{@
|
37
|
+
File.join(hidden_dir_path(type), "#{@project_deployment.name}.yml")
|
53
38
|
end
|
54
39
|
|
55
40
|
def hidden_dir_path(name)
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "membrane"
|
2
|
+
module Bosh::Workspace
|
3
|
+
class ProjectDeployment
|
4
|
+
include Bosh::Cli::Validation
|
5
|
+
attr_writer :director_uuid
|
6
|
+
attr_reader :file
|
7
|
+
|
8
|
+
RELEASE_SCHEMA = Membrane::SchemaParser.parse do
|
9
|
+
{
|
10
|
+
"name" => String,
|
11
|
+
"version" => enum(Integer, "latest"),
|
12
|
+
"git" => String,
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
STEMCELL_SCHEMA = Membrane::SchemaParser.parse do
|
17
|
+
{
|
18
|
+
"name" => String,
|
19
|
+
"version" => enum(Integer, "latest"),
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
UUID_REGEX = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/
|
24
|
+
|
25
|
+
PROJECT_DEPLOYMENT_SCHEMA = Membrane::SchemaParser.parse do
|
26
|
+
{
|
27
|
+
"name" => String,
|
28
|
+
"director_uuid" => enum(UUID_REGEX, "current"),
|
29
|
+
optional("domain_name") => String,
|
30
|
+
"releases" => [RELEASE_SCHEMA],
|
31
|
+
"stemcells" => [STEMCELL_SCHEMA],
|
32
|
+
"templates" => [String],
|
33
|
+
"meta" => Hash
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def initialize(file)
|
38
|
+
@file = file
|
39
|
+
err("Deployment file does not exist: #{file}") unless File.exist? @file
|
40
|
+
@manifest = Psych.load(File.read(@file))
|
41
|
+
end
|
42
|
+
|
43
|
+
def perform_validation(options = {})
|
44
|
+
PROJECT_DEPLOYMENT_SCHEMA.validate @manifest
|
45
|
+
rescue Membrane::SchemaValidationError => e
|
46
|
+
errors << e.message
|
47
|
+
end
|
48
|
+
|
49
|
+
def director_uuid
|
50
|
+
@director_uuid || @manifest["director_uuid"]
|
51
|
+
end
|
52
|
+
|
53
|
+
def merged_file
|
54
|
+
@merged_file ||= begin
|
55
|
+
path = File.join(file_dirname, "../.deployments", file_basename)
|
56
|
+
FileUtils.mkpath File.dirname(path)
|
57
|
+
File.expand_path path
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
%w[name templates releases stemcells meta domain_name].each do |var|
|
62
|
+
define_method var do
|
63
|
+
@manifest[var]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def file_basename
|
70
|
+
File.basename(@file)
|
71
|
+
end
|
72
|
+
|
73
|
+
def file_dirname
|
74
|
+
File.dirname(@file)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -1,58 +1,66 @@
|
|
1
1
|
require "git"
|
2
|
-
module Bosh::
|
2
|
+
module Bosh::Workspace
|
3
3
|
class Release
|
4
|
+
attr_reader :name, :git_uri, :repo_dir
|
5
|
+
|
4
6
|
def initialize(release, releases_dir)
|
5
7
|
@name = release["name"]
|
6
|
-
@
|
8
|
+
@version_ref = release["version"]
|
7
9
|
@git_uri = release["git"]
|
8
|
-
@
|
10
|
+
@repo_dir = File.join(releases_dir, @name)
|
11
|
+
init_repo
|
9
12
|
end
|
10
13
|
|
11
|
-
def
|
12
|
-
repo.pull
|
13
|
-
repo.checkout(
|
14
|
+
def update_repo
|
15
|
+
@repo.pull
|
16
|
+
@repo.checkout(ref)
|
14
17
|
end
|
15
18
|
|
16
|
-
|
19
|
+
def manifest_file
|
20
|
+
File.join(repo_dir, manifest)
|
21
|
+
end
|
17
22
|
|
18
|
-
def
|
19
|
-
|
20
|
-
@repo ||= Git.open(repo_dir)
|
21
|
-
else
|
22
|
-
FileUtils.mkdir_p(@work_dir)
|
23
|
-
@repo = Git.clone(@git_uri, @name, path: @work_dir)
|
24
|
-
end
|
23
|
+
def manifest
|
24
|
+
final_releases[version]
|
25
25
|
end
|
26
26
|
|
27
|
-
def
|
28
|
-
|
27
|
+
def name_version
|
28
|
+
"#{name}/#{version}"
|
29
29
|
end
|
30
30
|
|
31
|
-
def
|
32
|
-
if @
|
33
|
-
|
34
|
-
|
35
|
-
version = @version.to_i
|
36
|
-
unless available_versions[version]
|
37
|
-
err("Could not find version: #{@version} for release: #{@name}")
|
38
|
-
end
|
39
|
-
version
|
31
|
+
def version
|
32
|
+
return final_releases.keys.sort.last if @version_ref == "latest"
|
33
|
+
unless final_releases[@version_ref.to_i]
|
34
|
+
err("Could not find version: #{@version_ref} for release: #{@name}")
|
40
35
|
end
|
36
|
+
@version_ref.to_i
|
41
37
|
end
|
42
38
|
|
39
|
+
private
|
40
|
+
|
43
41
|
# transforms releases/foo-1.yml, releases/bar-2.yml to:
|
44
42
|
# { "1" => foo-1.yml, "2" => bar-2.yml }
|
45
|
-
def
|
46
|
-
@
|
47
|
-
Hash[Dir[File.join(repo_dir, "releases", "*.yml")]
|
48
|
-
|
49
|
-
|
50
|
-
|
43
|
+
def final_releases
|
44
|
+
@final_releases ||= begin
|
45
|
+
Hash[Dir[File.join(repo_dir, "releases", "*.yml")]
|
46
|
+
.reject { |f| f[/index.yml/] }
|
47
|
+
.map { |dir| File.join("releases", File.basename(dir)) }
|
48
|
+
.map { |version| [version[/(\d+)/].to_i, version] }]
|
51
49
|
end
|
52
50
|
end
|
53
51
|
|
54
|
-
def
|
55
|
-
|
52
|
+
def ref
|
53
|
+
@repo.log.object(manifest).first
|
54
|
+
end
|
55
|
+
|
56
|
+
def init_repo
|
57
|
+
if File.directory?(repo_dir)
|
58
|
+
@repo ||= Git.open(repo_dir)
|
59
|
+
else
|
60
|
+
releases_dir = File.dirname(repo_dir)
|
61
|
+
FileUtils.mkdir_p(releases_dir)
|
62
|
+
@repo = Git.clone(@git_uri, @name, path: releases_dir)
|
63
|
+
end
|
56
64
|
end
|
57
65
|
end
|
58
66
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Bosh::Workspace
|
2
|
+
class Stemcell
|
3
|
+
attr_reader :name, :version, :file
|
4
|
+
|
5
|
+
def initialize(stemcell, stemcells_dir)
|
6
|
+
@name = stemcell["name"]
|
7
|
+
@version = stemcell["version"]
|
8
|
+
@file = File.join(stemcells_dir, file_name)
|
9
|
+
end
|
10
|
+
|
11
|
+
def name_version
|
12
|
+
"#{name}/#{version}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def file_name
|
16
|
+
name.gsub(/^bosh-/, "bosh-stemcell-#{version}-") + ".tgz"
|
17
|
+
end
|
18
|
+
|
19
|
+
def downloaded?
|
20
|
+
File.exists? file
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Bosh::Workspace
|
2
|
+
class StubFile
|
3
|
+
attr_reader :name, :director_uuid
|
4
|
+
|
5
|
+
def self.create(path, project_deployment)
|
6
|
+
self.new(project_deployment).tap { |stub| stub.write(path) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def initialize(project_deployment)
|
10
|
+
@name = project_deployment.name
|
11
|
+
@director_uuid = project_deployment.director_uuid
|
12
|
+
@releases = project_deployment.releases
|
13
|
+
@stemcells = project_deployment.stemcells
|
14
|
+
@meta = project_deployment.meta
|
15
|
+
end
|
16
|
+
|
17
|
+
def write(file)
|
18
|
+
IO.write file, content.to_yaml
|
19
|
+
end
|
20
|
+
|
21
|
+
def content
|
22
|
+
{
|
23
|
+
"name" => name,
|
24
|
+
"director_uuid" => director_uuid,
|
25
|
+
"releases" => releases,
|
26
|
+
"meta" => meta
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def releases
|
31
|
+
@releases.map { |r| r.select { |key| %w[name version].include?(key) } }
|
32
|
+
end
|
33
|
+
|
34
|
+
def meta
|
35
|
+
out = case @stemcells.size
|
36
|
+
when 1
|
37
|
+
{ "stemcell" => @stemcells.first }
|
38
|
+
else
|
39
|
+
{ "stemcells" => @stemcells }
|
40
|
+
end
|
41
|
+
out.merge(@meta)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: foo
|
2
|
+
|
3
|
+
networks:
|
4
|
+
- name: default
|
5
|
+
type: manual
|
6
|
+
|
7
|
+
jobs:
|
8
|
+
- name: first_job_az1
|
9
|
+
networks:
|
10
|
+
- name: default
|
11
|
+
static_ips:
|
12
|
+
- 10.0.0.50
|
13
|
+
|
14
|
+
- name: second_job_az1
|
15
|
+
networks:
|
16
|
+
- name: default
|
17
|
+
static_ips:
|
18
|
+
- 10.0.0.51
|
19
|
+
properties:
|
20
|
+
job1:
|
21
|
+
foo: bar
|
22
|
+
address: 10.0.0.50
|
@@ -0,0 +1,18 @@
|
|
1
|
+
networks:
|
2
|
+
- name: default
|
3
|
+
type: manual
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
- name: job1
|
7
|
+
networks:
|
8
|
+
- name: default
|
9
|
+
static_ips:
|
10
|
+
- 10.0.0.50
|
11
|
+
- name: job2
|
12
|
+
networks:
|
13
|
+
- name: default
|
14
|
+
static_ips:
|
15
|
+
- 10.0.0.51
|
16
|
+
- name: job3
|
17
|
+
networks:
|
18
|
+
- name: default
|