bosh-workspace 0.8.5 → 0.9.0.rc1
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +1 -2
- data/.ruby-gemset +1 -1
- data/.travis.yml +2 -0
- data/Guardfile +2 -2
- data/README.md +4 -4
- data/bosh-workspace.gemspec +2 -1
- data/lib/bosh/cli/commands/deployment_patch.rb +96 -0
- data/lib/bosh/cli/commands/prepare.rb +6 -4
- data/lib/bosh/workspace/credentials.rb +30 -0
- data/lib/bosh/workspace/deployment_patch.rb +90 -0
- data/lib/bosh/workspace/helpers/git_credentials_helper.rb +95 -0
- data/lib/bosh/workspace/helpers/spiff_helper.rb +1 -0
- data/lib/bosh/workspace/project_deployment.rb +2 -44
- data/lib/bosh/workspace/release.rb +20 -23
- data/lib/bosh/workspace/schemas/credentials.rb +27 -0
- data/lib/bosh/workspace/schemas/deployment_patch.rb +15 -0
- data/lib/bosh/workspace/schemas/project_deployment.rb +21 -0
- data/lib/bosh/workspace/schemas/releases.rb +16 -0
- data/lib/bosh/workspace/schemas/stemcells.rb +25 -0
- data/lib/bosh/workspace/shell.rb +67 -0
- data/lib/bosh/workspace/tasks/bosh_command_runner.rb +29 -0
- data/lib/bosh/workspace/tasks/deployment.rb +63 -0
- data/lib/bosh/workspace/tasks/workspace.rake +69 -0
- data/lib/bosh/workspace/tasks.rb +15 -0
- data/lib/bosh/workspace/version.rb +1 -1
- data/lib/bosh/workspace.rb +14 -0
- data/spec/assets/foo-boshrelease-repo-new-structure.zip +0 -0
- data/spec/assets/foo-boshrelease-repo-updated.zip +0 -0
- data/spec/assets/foo-boshrelease-repo.zip +0 -0
- data/spec/assets/foo-boshworkspace.zip +0 -0
- data/spec/commands/deployment_patch_spec.rb +152 -0
- data/spec/commands/prepare_spec.rb +5 -3
- data/spec/credentials_spec.rb +46 -0
- data/spec/deployment_patch_spec.rb +171 -0
- data/spec/helpers/git_credentials_helper_spec.rb +160 -0
- data/spec/helpers/spiff_helper_spec.rb +16 -3
- data/spec/project_deployment_spec.rb +52 -163
- data/spec/release_spec.rb +208 -80
- data/spec/schemas/credentials_spec.rb +28 -0
- data/spec/schemas/deployment_patch_spec.rb +30 -0
- data/spec/schemas/project_deployment_spec.rb +45 -0
- data/spec/schemas/releases_spec.rb +31 -0
- data/spec/schemas/stemcells_spec.rb +37 -0
- data/spec/shell_spec.rb +70 -0
- data/spec/spec_helper.rb +11 -5
- data/spec/support/shared_contexts/rake.rb +37 -0
- data/spec/tasks/bosh_command_runner_spec.rb +39 -0
- data/spec/tasks/deployment_spec.rb +80 -0
- data/spec/tasks/workspace_task_spec.rb +99 -0
- metadata +69 -7
@@ -0,0 +1,25 @@
|
|
1
|
+
module Bosh::Workspace
|
2
|
+
module Schemas
|
3
|
+
class Stemcells < Membrane::Schemas::Base
|
4
|
+
def validate(object)
|
5
|
+
Membrane::SchemaParser.parse do
|
6
|
+
[{
|
7
|
+
"name" => String,
|
8
|
+
"version" => StemcellVersion.new
|
9
|
+
}]
|
10
|
+
end.validate object
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class StemcellVersion < Membrane::Schemas::Base
|
15
|
+
def validate(object)
|
16
|
+
return if object.is_a? Integer
|
17
|
+
return if object.is_a? Float
|
18
|
+
return if object == "latest"
|
19
|
+
return if object.to_s =~ /^\d+\.\d+$/
|
20
|
+
raise Membrane::SchemaValidationError.new(
|
21
|
+
"Should match: latest, version.patch or version. Given: #{object}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Bosh
|
2
|
+
module Workspace
|
3
|
+
class Shell
|
4
|
+
def initialize(stdout = $stdout)
|
5
|
+
@stdout = stdout
|
6
|
+
end
|
7
|
+
|
8
|
+
def run(command, options = {})
|
9
|
+
output_lines = run_command(command, options)
|
10
|
+
output_lines = tail(output_lines, options)
|
11
|
+
|
12
|
+
command_output = output_lines.join("\n")
|
13
|
+
report(command, command_output, options)
|
14
|
+
command_output
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :stdout
|
20
|
+
|
21
|
+
def run_command(command, options)
|
22
|
+
stdout.puts command if options[:output_command]
|
23
|
+
lines = []
|
24
|
+
|
25
|
+
if options[:env]
|
26
|
+
# Wrap in a shell because existing api to Shell#run takes a string
|
27
|
+
# which makes it really hard to pass it to popen with custom environment.
|
28
|
+
popen_args = [options[:env], ENV['SHELL'] || 'bash', '-c', command]
|
29
|
+
else
|
30
|
+
popen_args = command
|
31
|
+
end
|
32
|
+
|
33
|
+
IO.popen(popen_args) do |io|
|
34
|
+
io.each do |line|
|
35
|
+
stdout.puts line.chomp
|
36
|
+
stdout.flush
|
37
|
+
lines << line.chomp
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
lines
|
42
|
+
end
|
43
|
+
|
44
|
+
def tail(lines, options)
|
45
|
+
line_number = options[:last_number]
|
46
|
+
line_number ? lines.last(line_number) : lines
|
47
|
+
end
|
48
|
+
|
49
|
+
def report(cmd, command_output, options)
|
50
|
+
return if command_exited_successfully?
|
51
|
+
|
52
|
+
err_msg = "Failed: '#{cmd}' from #{pwd}, with exit status #{$?.to_i}\n\n #{command_output}"
|
53
|
+
options[:ignore_failures] ? stdout.puts("#{err_msg}, continuing anyway") : raise(err_msg)
|
54
|
+
end
|
55
|
+
|
56
|
+
def command_exited_successfully?
|
57
|
+
$?.success?
|
58
|
+
end
|
59
|
+
|
60
|
+
def pwd
|
61
|
+
Dir.pwd
|
62
|
+
rescue Errno::ENOENT
|
63
|
+
'a deleted directory'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Bosh::Workspace::Tasks
|
2
|
+
class BoshCommandRunner
|
3
|
+
attr_reader :target, :username, :password
|
4
|
+
attr_accessor :deployment_file
|
5
|
+
|
6
|
+
def initialize(target, username, password)
|
7
|
+
@target = target
|
8
|
+
@username = username
|
9
|
+
@password = password
|
10
|
+
@shell = Bosh::Workspace::Shell.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def run(command, options = {})
|
14
|
+
options.merge! default_options
|
15
|
+
args = ['-n', '-t', target]
|
16
|
+
args.concat ['-d', deployment_file] if deployment_file
|
17
|
+
@shell.run "bundle exec bosh #{args.join(' ')} #{command}", options
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def default_options
|
23
|
+
{
|
24
|
+
output_command: true,
|
25
|
+
env: { "BOSH_USER" => username, "BOSH_PASSWORD" => password }
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Bosh::Workspace::Tasks
|
2
|
+
class Deployment
|
3
|
+
def initialize(deployment)
|
4
|
+
schema.validate deployment
|
5
|
+
@raw = OpenStruct.new(deployment)
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
file = File.join 'deployments', file_name
|
10
|
+
YAML.load_file(file)["name"]
|
11
|
+
end
|
12
|
+
|
13
|
+
def target
|
14
|
+
return @raw.target unless @raw.target =~ /@/
|
15
|
+
@raw.target.split('@')[1]
|
16
|
+
end
|
17
|
+
|
18
|
+
def username
|
19
|
+
return "admin" unless @raw.target =~ /@/
|
20
|
+
@raw.target.match(/^([^@:]+)/)[1] || "admin"
|
21
|
+
end
|
22
|
+
|
23
|
+
def password
|
24
|
+
return "admin" unless @raw.target =~ /@/
|
25
|
+
match = @raw.target.match(/^[^:@]+:([^@]+)/)
|
26
|
+
match && match[1] || "admin"
|
27
|
+
end
|
28
|
+
|
29
|
+
def merged_file
|
30
|
+
File.join ".deployments", file_name
|
31
|
+
end
|
32
|
+
|
33
|
+
def file_name
|
34
|
+
@raw.name + ".yml"
|
35
|
+
end
|
36
|
+
|
37
|
+
def errands
|
38
|
+
@raw.errands
|
39
|
+
end
|
40
|
+
|
41
|
+
def apply_patch
|
42
|
+
@raw.apply_patch
|
43
|
+
end
|
44
|
+
|
45
|
+
def create_patch
|
46
|
+
@raw.create_patch
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def schema
|
52
|
+
Membrane::SchemaParser.parse do
|
53
|
+
{
|
54
|
+
"name" => /^((?!\.yml).)*$/, # Should not contain .yml
|
55
|
+
"target" => String,
|
56
|
+
optional("apply_patch") => String,
|
57
|
+
optional("create_patch") => String,
|
58
|
+
optional("errands") => [String]
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
namespace :workspace do
|
2
|
+
include Bosh::Workspace::Tasks
|
3
|
+
|
4
|
+
desc "Apply or create patches as defined in deployments.yml"
|
5
|
+
task :patch do
|
6
|
+
with_deployments do |deployment|
|
7
|
+
if apply_patch_path = deployment.apply_patch
|
8
|
+
bosh "apply deployment patch #{apply_patch_path}"
|
9
|
+
end
|
10
|
+
|
11
|
+
if create_patch_path = deployment.create_patch
|
12
|
+
bosh "create deployment patch #{create_patch_path}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Deploy deployments as defined in deployments.yml"
|
18
|
+
task :deploy do
|
19
|
+
with_deployments do
|
20
|
+
bosh "prepare deployment"
|
21
|
+
bosh_deploy
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
desc "Verifies deployments by running errands specified in deployments.yml"
|
26
|
+
task :run_errands do
|
27
|
+
with_deployments do |deployment|
|
28
|
+
deployment.errands.each do |errand|
|
29
|
+
bosh "run errand #{errand}"
|
30
|
+
end if deployment.errands
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "Cleans up by deleting all deployments specified in deployments.yml"
|
35
|
+
task :clean do
|
36
|
+
unless ENV["DESTROY_DEPLOYMENTS"]
|
37
|
+
raise "Set DESTROY_DEPLOYMENTS to confirm deployment destruction"
|
38
|
+
end
|
39
|
+
|
40
|
+
with_deployments(set_deployment: false) do |deployment|
|
41
|
+
bosh "delete deployment #{deployment.name} --force", ignore_failures: true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def with_deployments(options = {})
|
46
|
+
deployments.each do |d|
|
47
|
+
@cli = BoshCommandRunner.new(d.target, d.username, d.password)
|
48
|
+
unless options[:set_deployment] == false
|
49
|
+
@cli.deployment_file = d.merged_file
|
50
|
+
end
|
51
|
+
yield d
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def deployments
|
56
|
+
@deployments ||= begin
|
57
|
+
YAML.load_file("deployments.yml").map { |d| Deployment.new(d) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def bosh_deploy
|
62
|
+
out = bosh("deploy", last_number: 1)
|
63
|
+
exit 1 if out =~ /error/
|
64
|
+
end
|
65
|
+
|
66
|
+
def bosh(command, options = {})
|
67
|
+
@cli.run command, options
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "membrane"
|
3
|
+
|
4
|
+
module Bosh
|
5
|
+
module Workspace
|
6
|
+
module Tasks; end
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
require "bosh/workspace/shell"
|
11
|
+
require "bosh/workspace/tasks/bosh_command_runner.rb"
|
12
|
+
require "bosh/workspace/tasks/deployment.rb"
|
13
|
+
|
14
|
+
rake_paths = File.expand_path('tasks/**/*.rake', File.dirname(__FILE__))
|
15
|
+
Dir.glob(rake_paths).each { |r| import r } if defined? import
|
data/lib/bosh/workspace.rb
CHANGED
@@ -1,17 +1,31 @@
|
|
1
1
|
module Bosh; module Workspace; end; end
|
2
2
|
|
3
|
+
require "membrane"
|
4
|
+
require "shellwords"
|
5
|
+
require "rugged"
|
6
|
+
require "hashdiff"
|
3
7
|
require "cli/core_ext"
|
4
8
|
require "cli/validation"
|
5
9
|
|
6
10
|
require "bosh/workspace/helpers/spiff_helper"
|
7
11
|
require "bosh/workspace/helpers/project_deployment_helper"
|
12
|
+
require "bosh/workspace/helpers/git_credentials_helper"
|
8
13
|
require "bosh/workspace/helpers/release_helper"
|
9
14
|
require "bosh/workspace/helpers/stemcell_helper"
|
10
15
|
require "bosh/workspace/helpers/dns_helper"
|
11
16
|
|
17
|
+
require "bosh/workspace/schemas/project_deployment"
|
18
|
+
require "bosh/workspace/schemas/deployment_patch"
|
19
|
+
require "bosh/workspace/schemas/releases"
|
20
|
+
require "bosh/workspace/schemas/stemcells"
|
21
|
+
require "bosh/workspace/schemas/credentials"
|
22
|
+
|
23
|
+
require "bosh/workspace/shell"
|
12
24
|
require "bosh/workspace/manifest_builder"
|
13
25
|
require "bosh/workspace/release"
|
14
26
|
require "bosh/workspace/stemcell"
|
15
27
|
require "bosh/workspace/project_deployment"
|
16
28
|
require "bosh/workspace/stub_file"
|
29
|
+
require "bosh/workspace/deployment_patch"
|
30
|
+
require "bosh/workspace/credentials"
|
17
31
|
require "bosh/workspace/version"
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require "bosh/cli/commands/deployment_patch"
|
2
|
+
|
3
|
+
module Bosh::Cli::Command
|
4
|
+
include Bosh::Workspace
|
5
|
+
|
6
|
+
describe DeploymentPatch do
|
7
|
+
let(:command) { DeploymentPatch.new }
|
8
|
+
let(:patch) do
|
9
|
+
instance_double 'Bosh::Workspace::DeploymentPatch', templates_ref: ref
|
10
|
+
end
|
11
|
+
let(:current_patch) { instance_double 'Bosh::Workspace::DeploymentPatch' }
|
12
|
+
let(:deployment_file) { 'deployments/foo.yml' }
|
13
|
+
let(:patch_file) { 'patch.yml' }
|
14
|
+
let(:project_dir) { File.realpath Dir.mktmpdir }
|
15
|
+
let(:changes?) { nil }
|
16
|
+
let(:valid?) { true }
|
17
|
+
let(:ref) { "baz" }
|
18
|
+
let(:changes) do
|
19
|
+
{ stemcells: "foo", releases: "bar", templates_ref: ref }
|
20
|
+
end
|
21
|
+
|
22
|
+
before do
|
23
|
+
Dir.chdir project_dir
|
24
|
+
allow(Bosh::Workspace::DeploymentPatch).to receive(:create)
|
25
|
+
.with(deployment_file, /templates/).and_return(current_patch)
|
26
|
+
allow(Bosh::Workspace::DeploymentPatch).to receive(:from_file)
|
27
|
+
.with(patch_file).and_return(patch)
|
28
|
+
allow(current_patch).to receive(:changes?).with(patch)
|
29
|
+
.and_return(changes?)
|
30
|
+
expect(command).to receive(:require_project_deployment)
|
31
|
+
allow(command).to receive_message_chain("project_deployment.file")
|
32
|
+
.and_return(deployment_file)
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.create' do
|
36
|
+
it 'writes to file' do
|
37
|
+
expect(current_patch).to receive(:to_file).with(patch_file)
|
38
|
+
expect(command).to receive(:say).with /wrote patch/i
|
39
|
+
command.create(patch_file)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '.apply' do
|
44
|
+
let(:patch_valid?) { true }
|
45
|
+
|
46
|
+
before do
|
47
|
+
expect(patch).to receive(:valid?).and_return(patch_valid?)
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with non valid patch' do
|
51
|
+
let(:patch_valid?) { false }
|
52
|
+
|
53
|
+
it "raises an error" do
|
54
|
+
expect(patch).to receive(:errors).and_return(['foo', 'bar'])
|
55
|
+
expect(command).to receive(:say).with(/validation errors/i)
|
56
|
+
expect(command).to receive(:say).with(/foo/)
|
57
|
+
expect(command).to receive(:say).with(/bar/)
|
58
|
+
expect { command.apply(patch_file) }.to raise_error(/is not valid/)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with changes' do
|
63
|
+
let(:changes?) { true }
|
64
|
+
let(:index) do
|
65
|
+
instance_double('Rugged::Index',
|
66
|
+
read_tree: true, write_tree: true, add_all: true)
|
67
|
+
end
|
68
|
+
let(:repo) { instance_double 'Rugged::Repository', index: index }
|
69
|
+
|
70
|
+
def expect_patch_changes_table
|
71
|
+
expect(command).to receive(:say) do |s|
|
72
|
+
subject = s.to_s.delete ' '
|
73
|
+
expect(subject).to include "stemcells|foo"
|
74
|
+
expect(subject).to include "releases|bar"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
before do
|
79
|
+
allow(repo).to receive_message_chain('head.target.tree')
|
80
|
+
expect(current_patch).to receive(:changes).with(patch)
|
81
|
+
.and_return(changes)
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'no dry-run' do
|
85
|
+
before do
|
86
|
+
allow(command).to receive(:fetch_repo).with(/templates/)
|
87
|
+
expect(patch).to receive(:apply).with(deployment_file, /templates/)
|
88
|
+
expect(command).to receive(:say).with /successfully applied/i
|
89
|
+
expect_patch_changes_table
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'without no-commit' do
|
93
|
+
before do
|
94
|
+
expect(Rugged::Repository).to receive(:new)
|
95
|
+
.with(project_dir).and_return(repo)
|
96
|
+
end
|
97
|
+
|
98
|
+
def expect_commit(message)
|
99
|
+
expect(Rugged::Commit).to receive(:create) do |repo, options|
|
100
|
+
expect(options[:message]).to match message
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'applies changes, shows changes and commits' do
|
105
|
+
expect_commit "Applied stemcells foo," \
|
106
|
+
" releases bar, templates_ref baz"
|
107
|
+
command.apply(patch_file)
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'without templates_ref' do
|
111
|
+
let(:ref) { nil }
|
112
|
+
let(:changes) do
|
113
|
+
{ stemcells: "foo", releases: "bar" }
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'applies changes, shows changes and commits' do
|
117
|
+
expect_commit("Applied stemcells foo, releases bar")
|
118
|
+
expect(command).to_not receive(:fetch_repo)
|
119
|
+
command.apply(patch_file)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context 'no-commit' do
|
125
|
+
it 'applies changes and shows changes' do
|
126
|
+
command.add_option(:no_commit, true)
|
127
|
+
command.apply(patch_file)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'dry-run' do
|
133
|
+
it 'only shows changes' do
|
134
|
+
expect(command).to receive(:say).with /deployment patch/i
|
135
|
+
expect_patch_changes_table
|
136
|
+
command.add_option(:dry_run, true)
|
137
|
+
command.apply(patch_file)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'without changes' do
|
143
|
+
let(:changes?) { false }
|
144
|
+
|
145
|
+
it 'says no changes' do
|
146
|
+
expect(command).to receive(:say).with /no changes/i
|
147
|
+
command.apply(patch_file)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
@@ -5,7 +5,7 @@ describe Bosh::Cli::Command::Prepare do
|
|
5
5
|
let(:command) { Bosh::Cli::Command::Prepare.new }
|
6
6
|
let(:release) do
|
7
7
|
instance_double("Bosh::Workspace::Release",
|
8
|
-
name: "foo", version: "1", repo_dir: ".releases/foo",
|
8
|
+
name: "foo", version: "1", repo_dir: ".releases/foo", git_url: "/.git",
|
9
9
|
name_version: "foo/1", manifest_file: "releases/foo-1.yml")
|
10
10
|
end
|
11
11
|
let(:stemcell) do
|
@@ -24,7 +24,7 @@ describe Bosh::Cli::Command::Prepare do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
describe "prepare_release(s/_repos)" do
|
27
|
-
let(:releases) { [
|
27
|
+
let(:releases) { [release] }
|
28
28
|
let(:stemcells) { [] }
|
29
29
|
let(:ref) { nil }
|
30
30
|
|
@@ -33,6 +33,8 @@ describe Bosh::Cli::Command::Prepare do
|
|
33
33
|
expect(release).to receive(:ref).and_return(ref)
|
34
34
|
expect(command).to receive(:release_uploaded?)
|
35
35
|
.with(release.name, release.version).and_return(release_uploaded)
|
36
|
+
expect(command).to receive(:fetch_or_clone_repo)
|
37
|
+
.with(release.repo_dir, release.git_url)
|
36
38
|
end
|
37
39
|
|
38
40
|
context "release uploaded" do
|
@@ -80,7 +82,7 @@ describe Bosh::Cli::Command::Prepare do
|
|
80
82
|
context "stemcell not uploaded" do
|
81
83
|
let(:stemcell_uploaded) { false }
|
82
84
|
|
83
|
-
before do
|
85
|
+
before do
|
84
86
|
allow(stemcell).to receive(:downloaded?)
|
85
87
|
.and_return(stemcell_downloaded)
|
86
88
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Bosh::Workspace
|
2
|
+
describe Credentials do
|
3
|
+
let(:credentials) do
|
4
|
+
[{ "url" => "foo", "private_key" => "foobarkey" }]
|
5
|
+
end
|
6
|
+
|
7
|
+
before do
|
8
|
+
expect(YAML).to receive(:load_file).with(:file).and_return(credentials)
|
9
|
+
end
|
10
|
+
|
11
|
+
subject do
|
12
|
+
Credentials.new(:file)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#find_by_url' do
|
16
|
+
it "returns credentials when found multiple times" do
|
17
|
+
expect(subject.find_by_url("foo")).to eq({ private_key: "foobarkey" })
|
18
|
+
expect(subject.find_by_url("foo")).to eq({ private_key: "foobarkey" })
|
19
|
+
end
|
20
|
+
|
21
|
+
it "returns nil when not found" do
|
22
|
+
expect(subject.find_by_url("bar")).to be nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#perform_validation' do
|
27
|
+
context "valid" do
|
28
|
+
it "validates" do
|
29
|
+
allow_any_instance_of(Schemas::Credentials)
|
30
|
+
.to receive(:validate).with(credentials)
|
31
|
+
expect(subject).to be_valid
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "invalid" do
|
36
|
+
it "has errors" do
|
37
|
+
allow_any_instance_of(Schemas::Credentials)
|
38
|
+
.to receive(:validate).with(credentials)
|
39
|
+
.and_raise(Membrane::SchemaValidationError.new("foo"))
|
40
|
+
expect(subject).to_not be_valid
|
41
|
+
expect(subject.errors).to include "foo"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|