vcloud-core 0.6.0 → 0.7.0
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.
- data/CHANGELOG.md +13 -0
- data/README.md +1 -35
- data/bin/vcloud-login +5 -0
- data/jenkins.sh +2 -11
- data/jenkins_integration_tests.sh +3 -10
- data/jenkins_tests.sh +37 -0
- data/lib/vcloud/core.rb +1 -0
- data/lib/vcloud/core/login_cli.rb +84 -0
- data/lib/vcloud/core/version.rb +1 -1
- data/lib/vcloud/fog.rb +34 -0
- data/lib/vcloud/fog/login.rb +38 -0
- data/spec/integration/fog/login_manual.rb +47 -0
- data/spec/integration/fog/login_spec.rb +30 -0
- data/spec/vcloud/core/login_cli_spec.rb +147 -0
- data/spec/vcloud/core/query_cli_spec.rb +2 -2
- data/spec/vcloud/fog/login_spec.rb +48 -0
- data/spec/vcloud/fog_spec.rb +30 -0
- data/vcloud-core.gemspec +1 -0
- metadata +34 -4
- data/tools/fog_credentials.rb +0 -17
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 0.7.0 (2014-07-28)
|
2
|
+
|
3
|
+
Features:
|
4
|
+
|
5
|
+
- New vcloud-login tool for fetching session tokens without the need to
|
6
|
+
store your password in a plaintext FOG_RC file.
|
7
|
+
|
8
|
+
Deprecated:
|
9
|
+
|
10
|
+
- Deprecate the use of :vcloud_director_password in a plaintext FOG_RC
|
11
|
+
file. A warning will be printed to STDERR at load time. Please use
|
12
|
+
vcloud-login instead.
|
13
|
+
|
1
14
|
## 0.6.0 (2014-07-14)
|
2
15
|
|
3
16
|
API changes:
|
data/README.md
CHANGED
@@ -20,41 +20,7 @@ Or install it yourself as:
|
|
20
20
|
|
21
21
|
## Credentials
|
22
22
|
|
23
|
-
|
24
|
-
credentials that allow it to talk to a vCloud Director environment.
|
25
|
-
|
26
|
-
1. Create a '.fog' file in your home directory.
|
27
|
-
|
28
|
-
For example:
|
29
|
-
|
30
|
-
test_credentials:
|
31
|
-
vcloud_director_host: 'host.api.example.com'
|
32
|
-
vcloud_director_username: 'username@org_name'
|
33
|
-
vcloud_director_password: ''
|
34
|
-
|
35
|
-
2. Obtain a session token. First, curl the API:
|
36
|
-
|
37
|
-
curl -D- -d '' \
|
38
|
-
-H 'Accept: application/*+xml;version=5.1' -u '<username>@<org_name>' \
|
39
|
-
https://<host.api.example.com>/api/sessions
|
40
|
-
|
41
|
-
This will prompt for your password.
|
42
|
-
|
43
|
-
From the headers returned, the value of the `x-vcloud-authorization` header is your
|
44
|
-
session token, and this will be valid for 30 minutes idle - any activity will extend
|
45
|
-
its life by another 30 minutes.
|
46
|
-
|
47
|
-
3. Specify your credentials and session token at the beginning of the command. For example:
|
48
|
-
|
49
|
-
FOG_CREDENTIAL=test_credentials \
|
50
|
-
FOG_VCLOUD_TOKEN=AAAABBBBBCCCCCCDDDDDDEEEEEEFFFFF= \
|
51
|
-
vcloud-query
|
52
|
-
|
53
|
-
You may find it easier to export one or both of the values as environment variables.
|
54
|
-
|
55
|
-
**NB** It is also possible to sidestep the need for the session token by saving your
|
56
|
-
password in the fog file. This is **not recommended**.
|
57
|
-
|
23
|
+
Please see the [vcloud-tools usage documentation](http://gds-operations.github.io/vcloud-tools/usage/).
|
58
24
|
|
59
25
|
## vCloud Query
|
60
26
|
|
data/bin/vcloud-login
ADDED
data/jenkins.sh
CHANGED
@@ -1,14 +1,5 @@
|
|
1
|
-
#!/bin/bash
|
1
|
+
#!/bin/bash
|
2
2
|
set -e
|
3
3
|
|
4
|
-
|
5
|
-
bundle install --path "${HOME}/bundles/${JOB_NAME}"
|
6
|
-
|
7
|
-
# Obtain the integration test parameters
|
8
|
-
git clone git@github.gds:gds/vcloud-tools-testing-config.git
|
9
|
-
mv vcloud-tools-testing-config/vcloud_tools_testing_config.yaml spec/integration/
|
10
|
-
rm -rf vcloud-tools-testing-config
|
11
|
-
|
12
|
-
bundle exec rake
|
13
|
-
RUBYOPT="-r ./tools/fog_credentials" bundle exec rake integration
|
4
|
+
./jenkins_tests.sh
|
14
5
|
bundle exec rake publish_gem
|
@@ -1,12 +1,5 @@
|
|
1
|
-
#!/bin/bash
|
1
|
+
#!/bin/bash
|
2
2
|
set -e
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
# Obtain the integration test parameters
|
8
|
-
git clone git@github.gds:gds/vcloud-tools-testing-config.git
|
9
|
-
mv vcloud-tools-testing-config/vcloud_tools_testing_config.yaml spec/integration/
|
10
|
-
rm -rf vcloud-tools-testing-config
|
11
|
-
|
12
|
-
RUBYOPT="-r ./tools/fog_credentials" bundle exec rake integration
|
4
|
+
# FIXME: Change the Carrenza job to use the following script directly.
|
5
|
+
./jenkins_tests.sh
|
data/jenkins_tests.sh
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
set -eu
|
3
|
+
|
4
|
+
function cleanup {
|
5
|
+
rm $FOG_RC
|
6
|
+
}
|
7
|
+
|
8
|
+
# Override default of ~/.fog and delete afterwards.
|
9
|
+
export FOG_RC=$(mktemp /tmp/vcloud_fog_rc.XXXXXXXXXX)
|
10
|
+
trap cleanup EXIT
|
11
|
+
|
12
|
+
cat <<EOF >${FOG_RC}
|
13
|
+
${FOG_CREDENTIAL}:
|
14
|
+
vcloud_director_host: '${API_HOST}'
|
15
|
+
vcloud_director_username: '${API_USERNAME}'
|
16
|
+
vcloud_director_password: ''
|
17
|
+
EOF
|
18
|
+
|
19
|
+
git clean -ffdx
|
20
|
+
|
21
|
+
# We wish to force using a version of ruby installed with rbenv, because the version of ruby shipped with
|
22
|
+
# Ubuntu 12.04 has a bug we hit in Psych when loading YAML files.
|
23
|
+
export RBENV_VERSION="1.9.3"
|
24
|
+
|
25
|
+
bundle install --path "${HOME}/bundles/${JOB_NAME}" --shebang="/usr/bin/env ruby"
|
26
|
+
|
27
|
+
# Obtain the integration test parameters
|
28
|
+
git clone git@github.gds:gds/vcloud-tools-testing-config.git
|
29
|
+
mv vcloud-tools-testing-config/vcloud_tools_testing_config.yaml spec/integration/
|
30
|
+
rm -rf vcloud-tools-testing-config
|
31
|
+
|
32
|
+
# Never log token to STDOUT.
|
33
|
+
set +x
|
34
|
+
eval $(printenv API_PASSWORD | bundle exec vcloud-login)
|
35
|
+
|
36
|
+
bundle exec rake
|
37
|
+
bundle exec rake integration
|
data/lib/vcloud/core.rb
CHANGED
@@ -11,6 +11,7 @@ require 'vcloud/core/compute_metadata'
|
|
11
11
|
require 'vcloud/core/vdc'
|
12
12
|
require 'vcloud/core/edge_gateway'
|
13
13
|
require 'vcloud/core/edge_gateway_interface'
|
14
|
+
require 'vcloud/core/login_cli'
|
14
15
|
require 'vcloud/core/vm'
|
15
16
|
require 'vcloud/core/vapp'
|
16
17
|
require 'vcloud/core/vapp_template'
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'highline'
|
3
|
+
|
4
|
+
module Vcloud
|
5
|
+
module Core
|
6
|
+
class LoginCli
|
7
|
+
def initialize(argv_array)
|
8
|
+
@usage_text = nil
|
9
|
+
|
10
|
+
parse(argv_array)
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
begin
|
15
|
+
pass = read_pass
|
16
|
+
puts Vcloud::Fog::Login.token_export(pass)
|
17
|
+
rescue => e
|
18
|
+
$stderr.puts(e)
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def parse(args)
|
26
|
+
opt_parser = OptionParser.new do |opts|
|
27
|
+
opts.banner = <<-EOS
|
28
|
+
Usage: #{$0} [options]
|
29
|
+
|
30
|
+
Utility for obtaining a Fog vCloud Director session token. It will output a
|
31
|
+
shell `export` command that can be consumed with:
|
32
|
+
|
33
|
+
eval $(FOG_CREDENTIAL=example #{$0})
|
34
|
+
|
35
|
+
It requires a Fog credentials file (e.g. `~/.fog`) with the host and user
|
36
|
+
set, but the password set to an empty string. The password can either be
|
37
|
+
entered interactively or piped in, for example from an environment variable:
|
38
|
+
|
39
|
+
printenv PASSWORD_VAR | FOG_CREDENTIAL=example #{$0}
|
40
|
+
|
41
|
+
EOS
|
42
|
+
|
43
|
+
opts.on("-h", "--help", "Print usage and exit") do
|
44
|
+
$stderr.puts opts
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("--version", "Display version and exit") do
|
49
|
+
puts Vcloud::Core::VERSION
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@usage_text = opt_parser.to_s
|
55
|
+
begin
|
56
|
+
opt_parser.parse!(args)
|
57
|
+
rescue OptionParser::InvalidOption => e
|
58
|
+
exit_error_usage(e)
|
59
|
+
end
|
60
|
+
|
61
|
+
if args.size > 0
|
62
|
+
exit_error_usage("too many arguments")
|
63
|
+
elsif args.size == 1
|
64
|
+
@type = args.first
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def read_pass
|
69
|
+
hl = HighLine.new($stdin, $stderr)
|
70
|
+
if STDIN.tty?
|
71
|
+
hl.ask("vCloud password: ") { |q| q.echo = "*" }
|
72
|
+
else
|
73
|
+
hl.ask("Reading password from pipe..")
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def exit_error_usage(error)
|
78
|
+
$stderr.puts "#{$0}: #{error}"
|
79
|
+
$stderr.puts @usage_text
|
80
|
+
exit 2
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
data/lib/vcloud/core/version.rb
CHANGED
data/lib/vcloud/fog.rb
CHANGED
@@ -1,5 +1,39 @@
|
|
1
1
|
require 'fog'
|
2
2
|
require 'vcloud/fog/content_types'
|
3
|
+
require 'vcloud/fog/login'
|
3
4
|
require 'vcloud/fog/relation'
|
4
5
|
require 'vcloud/fog/service_interface'
|
5
6
|
require 'vcloud/fog/model_interface'
|
7
|
+
|
8
|
+
module Vcloud
|
9
|
+
module Fog
|
10
|
+
TOKEN_ENV_VAR_NAME = 'FOG_VCLOUD_TOKEN'
|
11
|
+
FOG_CREDS_PASS_NAME = :vcloud_director_password
|
12
|
+
|
13
|
+
def self.check_credentials
|
14
|
+
pass = fog_credentials_pass
|
15
|
+
unless pass.nil? or pass.empty?
|
16
|
+
warn <<EOF
|
17
|
+
[WARNING] Storing :vcloud_director_password in your plaintext FOG_RC file is
|
18
|
+
insecure. Future releases of vcloud-core (and tools that depend on
|
19
|
+
it) will prevent you from doing this. Please use vcloud-login to
|
20
|
+
get a session token instead.
|
21
|
+
EOF
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.fog_credentials_pass
|
26
|
+
begin
|
27
|
+
pass = ::Fog.credentials[FOG_CREDS_PASS_NAME]
|
28
|
+
rescue ::Fog::Errors::LoadError
|
29
|
+
# Assume no password if Fog has been unable to load creds.
|
30
|
+
# Suppresses a noisy error about missing credentials.
|
31
|
+
pass = nil
|
32
|
+
end
|
33
|
+
|
34
|
+
pass
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
Vcloud::Fog.check_credentials
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'fog'
|
2
|
+
|
3
|
+
module Vcloud
|
4
|
+
module Fog
|
5
|
+
module Login
|
6
|
+
class << self
|
7
|
+
def token(pass)
|
8
|
+
check_plaintext_pass
|
9
|
+
token = get_token(pass)
|
10
|
+
|
11
|
+
return token
|
12
|
+
end
|
13
|
+
|
14
|
+
def token_export(*args)
|
15
|
+
return "export #{Vcloud::Fog::TOKEN_ENV_VAR_NAME}=#{token(*args)}"
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def check_plaintext_pass
|
21
|
+
pass = Vcloud::Fog::fog_credentials_pass
|
22
|
+
unless pass.nil? || pass.empty?
|
23
|
+
raise "Found plaintext #{Vcloud::Fog::FOG_CREDS_PASS_NAME} entry. Please set it to an empty string"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_token(pass)
|
28
|
+
ENV.delete(Vcloud::Fog::TOKEN_ENV_VAR_NAME)
|
29
|
+
vcloud = ::Fog::Compute::VcloudDirector.new({
|
30
|
+
Vcloud::Fog::FOG_CREDS_PASS_NAME => pass,
|
31
|
+
})
|
32
|
+
|
33
|
+
return vcloud.vcloud_token
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# These tests, which confirm that the Fog internals are performing a login
|
4
|
+
# and returning a new token, are not run automatically because they conflict
|
5
|
+
# with the use of vcloud-login in CI. Because we're using vcloud-login all
|
6
|
+
# of our tests should fail if the behaviour of Fog changes. However these
|
7
|
+
# may came in useful when debugging such a scenario.
|
8
|
+
|
9
|
+
describe Vcloud::Fog::Login do
|
10
|
+
let!(:mock_env) { ENV.clone }
|
11
|
+
|
12
|
+
before(:each) do
|
13
|
+
stub_const('ENV', mock_env)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#token" do
|
17
|
+
context "fog credentials without password" do
|
18
|
+
let(:token_length) { 44 }
|
19
|
+
let(:env_var_name) { 'FOG_VCLOUD_TOKEN' }
|
20
|
+
let!(:mock_fog_creds) { ::Fog.credentials.clone }
|
21
|
+
|
22
|
+
before(:each) do
|
23
|
+
@real_password = mock_fog_creds.delete(:vcloud_director_password)
|
24
|
+
allow(::Fog).to receive(:credentials).and_return(mock_fog_creds)
|
25
|
+
end
|
26
|
+
|
27
|
+
context "environment variable VCLOUD_FOG_TOKEN not set" do
|
28
|
+
it "should login and return a token" do
|
29
|
+
mock_env.delete(env_var_name)
|
30
|
+
token = subject.token(@real_password)
|
31
|
+
expect(token.size).to eq(token_length)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "environment variable VCLOUD_FOG_TOKEN is set" do
|
36
|
+
let(:old_token) { 'mekmitasdigoat' }
|
37
|
+
|
38
|
+
it "should login and return a token, ignoring the existing token" do
|
39
|
+
mock_env[env_var_name] = old_token
|
40
|
+
new_token = subject.token(@real_password)
|
41
|
+
expect(new_token).to_not eq(old_token)
|
42
|
+
expect(new_token.size).to eq(token_length)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vcloud::Fog::Login do
|
4
|
+
let!(:mock_env) { ENV.clone }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
stub_const('ENV', mock_env)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#token" do
|
11
|
+
context "unable to load credentials" do
|
12
|
+
it "should raise an exception succinctly listing the missing credentials" do
|
13
|
+
mock_env.clear
|
14
|
+
::Fog.credential = 'null'
|
15
|
+
::Fog.credentials_path = '/dev/null'
|
16
|
+
|
17
|
+
# This test is known to fail with a TypeError due to a bug in Ruby 1.9.3 that
|
18
|
+
# has since been fixed. See https://github.com/gds-operations/vcloud-core/pull/100
|
19
|
+
expect { ::Fog.credentials['doesnotexist'] }.to raise_error(
|
20
|
+
Fog::Errors::LoadError,
|
21
|
+
/^Missing Credentials\n/
|
22
|
+
)
|
23
|
+
expect { subject.token(@real_password) }.to raise_error(
|
24
|
+
ArgumentError,
|
25
|
+
/^Missing required arguments: vcloud_director_.*$/
|
26
|
+
)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class LoginCommandRun
|
4
|
+
attr_accessor :stdout, :stderr, :exitstatus
|
5
|
+
|
6
|
+
def initialize(args, stdin=nil)
|
7
|
+
out = StringIO.new
|
8
|
+
err = StringIO.new
|
9
|
+
|
10
|
+
if stdin
|
11
|
+
$stdin = StringIO.new
|
12
|
+
$stdin << stdin
|
13
|
+
$stdin.rewind
|
14
|
+
end
|
15
|
+
$stdout = out
|
16
|
+
$stderr = err
|
17
|
+
|
18
|
+
begin
|
19
|
+
Vcloud::Core::LoginCli.new(args).run
|
20
|
+
@exitstatus = 0
|
21
|
+
rescue SystemExit => e
|
22
|
+
# Capture exit(n) value.
|
23
|
+
@exitstatus = e.status
|
24
|
+
end
|
25
|
+
|
26
|
+
@stdout = out.string.strip
|
27
|
+
@stderr = err.string.strip
|
28
|
+
|
29
|
+
if stdin
|
30
|
+
$stdin = STDIN
|
31
|
+
end
|
32
|
+
$stdout = STDOUT
|
33
|
+
$stderr = STDERR
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe Vcloud::Core::LoginCli do
|
38
|
+
let(:stdin) { nil }
|
39
|
+
subject { LoginCommandRun.new(args, stdin) }
|
40
|
+
|
41
|
+
describe "normal usage" do
|
42
|
+
context "when given no arguments and a password on stdin" do
|
43
|
+
let(:args) { %w{} }
|
44
|
+
let(:pass) { 'supersekret' }
|
45
|
+
let(:stdin) { pass }
|
46
|
+
|
47
|
+
context "interactive tty" do
|
48
|
+
before(:each) do
|
49
|
+
expect(STDIN).to receive(:tty?).and_return(true)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should prompt on stderr so that stdout can be scripted and mask password input" do
|
53
|
+
expect(Vcloud::Fog::Login).to receive(:token_export).with(pass)
|
54
|
+
expect(subject.stderr).to eq("vCloud password: " + "*" * pass.size)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "non-interactive tty" do
|
59
|
+
before(:each) do
|
60
|
+
expect(STDIN).to receive(:tty?).and_return(false)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should write stderr message to say that it's reading from pipe and not echo any input" do
|
64
|
+
expect(Vcloud::Fog::Login).to receive(:token_export).with(pass)
|
65
|
+
expect(subject.stderr).to eq("Reading password from pipe..")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when asked to display version" do
|
71
|
+
let(:args) { %w{--version} }
|
72
|
+
|
73
|
+
it "should not call Login" do
|
74
|
+
expect(Vcloud::Fog::Login).not_to receive(:token_export)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should print version and exit normally" do
|
78
|
+
expect(subject.stdout).to eq(Vcloud::Core::VERSION)
|
79
|
+
expect(subject.exitstatus).to eq(0)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "when asked to display help" do
|
84
|
+
let(:args) { %w{--help} }
|
85
|
+
|
86
|
+
it "should not call Login" do
|
87
|
+
expect(Vcloud::Fog::Login).not_to receive(:token_export)
|
88
|
+
end
|
89
|
+
|
90
|
+
it "should print usage and exit normally" do
|
91
|
+
expect(subject.stderr).to match(/\AUsage: \S+ \[options\]\n/)
|
92
|
+
expect(subject.exitstatus).to eq(0)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "incorrect usage" do
|
98
|
+
shared_examples "print usage and exit abnormally" do |error|
|
99
|
+
it "should not call Login" do
|
100
|
+
expect(Vcloud::Fog::Login).not_to receive(:token_export)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "should print error message and usage" do
|
104
|
+
expect(subject.stderr).to match(/\A\S+: #{error}\nUsage: \S+/)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should exit abnormally for incorrect usage" do
|
108
|
+
expect(subject.exitstatus).to eq(2)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
context "when given more than one argument" do
|
113
|
+
let(:args) { %w{an_extra_arg} }
|
114
|
+
|
115
|
+
it_behaves_like "print usage and exit abnormally", "too many arguments"
|
116
|
+
end
|
117
|
+
|
118
|
+
context "when given an unrecognised argument" do
|
119
|
+
let(:args) { %w{--this-is-garbage} }
|
120
|
+
|
121
|
+
it_behaves_like "print usage and exit abnormally", "invalid option: --this-is-garbage"
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe "error handling" do
|
126
|
+
context "when underlying code raises an exception" do
|
127
|
+
let(:args) { %w{} }
|
128
|
+
# We have to pass a string here to prevent highline blowing up. This
|
129
|
+
# appears to be related to swapping out $stdin for StringIO and can't
|
130
|
+
# be reproduced by normal CLI use.
|
131
|
+
let(:pass) { 'some string' }
|
132
|
+
let(:stdin) { pass }
|
133
|
+
let(:exception_string) { 'something went horribly wrong' }
|
134
|
+
|
135
|
+
it "should print error without backtrace and exit abnormally" do
|
136
|
+
expect(Vcloud::Fog::Login).to receive(:token_export).
|
137
|
+
and_raise(exception_string)
|
138
|
+
if STDIN.tty?
|
139
|
+
expect(subject.stderr).to eq("vCloud password: #{'*' * pass.size}\n#{exception_string}")
|
140
|
+
else
|
141
|
+
expect(subject.stderr).to eq("Reading password from pipe..\n#{exception_string}")
|
142
|
+
end
|
143
|
+
expect(subject.exitstatus).to eq(1)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
class
|
3
|
+
class QueryCommandRun
|
4
4
|
attr_accessor :stdout, :stderr, :exitstatus
|
5
5
|
|
6
6
|
def initialize(args)
|
@@ -27,7 +27,7 @@ class CommandRun
|
|
27
27
|
end
|
28
28
|
|
29
29
|
describe Vcloud::Core::QueryCli do
|
30
|
-
subject {
|
30
|
+
subject { QueryCommandRun.new(args) }
|
31
31
|
let(:mock_query) {
|
32
32
|
double(:query, :run => true)
|
33
33
|
}
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
describe Vcloud::Fog::Login do
|
5
|
+
describe "#token" do
|
6
|
+
it "should return the output from get_token" do
|
7
|
+
expect(subject).to receive(:check_plaintext_pass)
|
8
|
+
expect(subject).to receive(:get_token).and_return('mekmitasdigoat')
|
9
|
+
expect(subject.token('supersekret')).to eq("mekmitasdigoat")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#token_export" do
|
14
|
+
it "should call #token with pass arg and return shell export string" do
|
15
|
+
expect(subject).to receive(:token).with('supersekret').and_return('mekmitasdigoat')
|
16
|
+
expect(subject.token_export("supersekret")).to eq("export FOG_VCLOUD_TOKEN=mekmitasdigoat")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#check_plaintext_pass" do
|
21
|
+
context "vcloud_director_password not set" do
|
22
|
+
it "should not raise an exception" do
|
23
|
+
expect(Vcloud::Fog).to receive(:fog_credentials_pass).and_return(nil)
|
24
|
+
expect(subject).to receive(:get_token)
|
25
|
+
expect { subject.token('supersekret') }.not_to raise_error
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "vcloud_director_password empty string" do
|
30
|
+
it "should not raise an exception" do
|
31
|
+
expect(Vcloud::Fog).to receive(:fog_credentials_pass).and_return('')
|
32
|
+
expect(subject).to receive(:get_token)
|
33
|
+
expect { subject.token('supersekret') }.not_to raise_error
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context "vcloud_director_password non-empty string" do
|
38
|
+
it "should raise an exception" do
|
39
|
+
expect(Vcloud::Fog).to receive(:fog_credentials_pass).and_return('supersekret')
|
40
|
+
expect(subject).to_not receive(:get_token)
|
41
|
+
expect { subject.token('supersekret') }.to raise_error(
|
42
|
+
RuntimeError,
|
43
|
+
"Found plaintext vcloud_director_password entry. Please set it to an empty string"
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Vcloud::Fog do
|
4
|
+
describe "fog_credentials_pass" do
|
5
|
+
let(:subject) { Vcloud::Fog::fog_credentials_pass }
|
6
|
+
|
7
|
+
context "vcloud_director_password not set" do
|
8
|
+
it "should return nil" do
|
9
|
+
expect(::Fog).to receive(:credentials).and_return({})
|
10
|
+
expect(subject).to eq(nil)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "vcloud_director_password set" do
|
15
|
+
it "should return string" do
|
16
|
+
expect(::Fog).to receive(:credentials).and_return({
|
17
|
+
:vcloud_director_password => 'supersekret',
|
18
|
+
})
|
19
|
+
expect(subject).to eq('supersekret')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "Fog LoadError" do
|
24
|
+
it "should suppress exception and return nil" do
|
25
|
+
expect(::Fog).to receive(:credentials).and_raise(::Fog::Errors::LoadError)
|
26
|
+
expect(subject).to eq(nil)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/vcloud-core.gemspec
CHANGED
@@ -24,6 +24,7 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_runtime_dependency 'fog', '>= 1.22.0'
|
26
26
|
s.add_runtime_dependency 'mustache'
|
27
|
+
s.add_runtime_dependency 'highline'
|
27
28
|
s.add_development_dependency 'gem_publisher', '1.2.0'
|
28
29
|
s.add_development_dependency 'pry'
|
29
30
|
s.add_development_dependency 'rake'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vcloud-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-07-
|
12
|
+
date: 2014-07-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -43,6 +43,22 @@ dependencies:
|
|
43
43
|
- - ! '>='
|
44
44
|
- !ruby/object:Gem::Version
|
45
45
|
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: highline
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
46
62
|
- !ruby/object:Gem::Dependency
|
47
63
|
name: gem_publisher
|
48
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -160,6 +176,7 @@ description: Core tools for interacting with VMware vCloud Director. Includes VC
|
|
160
176
|
email:
|
161
177
|
- anna.shipman@digital.cabinet-office.gov.uk
|
162
178
|
executables:
|
179
|
+
- vcloud-login
|
163
180
|
- vcloud-query
|
164
181
|
extensions: []
|
165
182
|
extra_rdoc_files: []
|
@@ -172,9 +189,11 @@ files:
|
|
172
189
|
- LICENSE.txt
|
173
190
|
- README.md
|
174
191
|
- Rakefile
|
192
|
+
- bin/vcloud-login
|
175
193
|
- bin/vcloud-query
|
176
194
|
- jenkins.sh
|
177
195
|
- jenkins_integration_tests.sh
|
196
|
+
- jenkins_tests.sh
|
178
197
|
- lib/vcloud/core.rb
|
179
198
|
- lib/vcloud/core/compute_metadata.rb
|
180
199
|
- lib/vcloud/core/config_loader.rb
|
@@ -182,6 +201,7 @@ files:
|
|
182
201
|
- lib/vcloud/core/edge_gateway.rb
|
183
202
|
- lib/vcloud/core/edge_gateway_interface.rb
|
184
203
|
- lib/vcloud/core/entity.rb
|
204
|
+
- lib/vcloud/core/login_cli.rb
|
185
205
|
- lib/vcloud/core/metadata_helper.rb
|
186
206
|
- lib/vcloud/core/org_vdc_network.rb
|
187
207
|
- lib/vcloud/core/query.rb
|
@@ -194,6 +214,7 @@ files:
|
|
194
214
|
- lib/vcloud/core/vm.rb
|
195
215
|
- lib/vcloud/fog.rb
|
196
216
|
- lib/vcloud/fog/content_types.rb
|
217
|
+
- lib/vcloud/fog/login.rb
|
197
218
|
- lib/vcloud/fog/model_interface.rb
|
198
219
|
- lib/vcloud/fog/relation.rb
|
199
220
|
- lib/vcloud/fog/service_interface.rb
|
@@ -203,6 +224,8 @@ files:
|
|
203
224
|
- spec/integration/core/vapp_spec.rb
|
204
225
|
- spec/integration/core/vdc_spec.rb
|
205
226
|
- spec/integration/core/vm_spec.rb
|
227
|
+
- spec/integration/fog/login_manual.rb
|
228
|
+
- spec/integration/fog/login_spec.rb
|
206
229
|
- spec/integration/vcloud_tools_testing_config.yaml.template
|
207
230
|
- spec/spec_helper.rb
|
208
231
|
- spec/support/integration_helper.rb
|
@@ -219,6 +242,7 @@ files:
|
|
219
242
|
- spec/vcloud/core/data/working_with_defaults.yaml
|
220
243
|
- spec/vcloud/core/edge_gateway_interface_spec.rb
|
221
244
|
- spec/vcloud/core/edge_gateway_spec.rb
|
245
|
+
- spec/vcloud/core/login_cli_spec.rb
|
222
246
|
- spec/vcloud/core/metadata_helper_spec.rb
|
223
247
|
- spec/vcloud/core/org_vdc_network_spec.rb
|
224
248
|
- spec/vcloud/core/query_cli_spec.rb
|
@@ -229,8 +253,9 @@ files:
|
|
229
253
|
- spec/vcloud/core/vdc_spec.rb
|
230
254
|
- spec/vcloud/core/vm_spec.rb
|
231
255
|
- spec/vcloud/fog/fog_model_interface_spec.rb
|
256
|
+
- spec/vcloud/fog/login_spec.rb
|
232
257
|
- spec/vcloud/fog/service_interface_spec.rb
|
233
|
-
-
|
258
|
+
- spec/vcloud/fog_spec.rb
|
234
259
|
- vcloud-core.gemspec
|
235
260
|
homepage: http://github.com/gds-operations/vcloud-core
|
236
261
|
licenses:
|
@@ -253,7 +278,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
253
278
|
version: '0'
|
254
279
|
segments:
|
255
280
|
- 0
|
256
|
-
hash:
|
281
|
+
hash: 622735401989777949
|
257
282
|
requirements: []
|
258
283
|
rubyforge_project:
|
259
284
|
rubygems_version: 1.8.23
|
@@ -267,6 +292,8 @@ test_files:
|
|
267
292
|
- spec/integration/core/vapp_spec.rb
|
268
293
|
- spec/integration/core/vdc_spec.rb
|
269
294
|
- spec/integration/core/vm_spec.rb
|
295
|
+
- spec/integration/fog/login_manual.rb
|
296
|
+
- spec/integration/fog/login_spec.rb
|
270
297
|
- spec/integration/vcloud_tools_testing_config.yaml.template
|
271
298
|
- spec/spec_helper.rb
|
272
299
|
- spec/support/integration_helper.rb
|
@@ -283,6 +310,7 @@ test_files:
|
|
283
310
|
- spec/vcloud/core/data/working_with_defaults.yaml
|
284
311
|
- spec/vcloud/core/edge_gateway_interface_spec.rb
|
285
312
|
- spec/vcloud/core/edge_gateway_spec.rb
|
313
|
+
- spec/vcloud/core/login_cli_spec.rb
|
286
314
|
- spec/vcloud/core/metadata_helper_spec.rb
|
287
315
|
- spec/vcloud/core/org_vdc_network_spec.rb
|
288
316
|
- spec/vcloud/core/query_cli_spec.rb
|
@@ -293,4 +321,6 @@ test_files:
|
|
293
321
|
- spec/vcloud/core/vdc_spec.rb
|
294
322
|
- spec/vcloud/core/vm_spec.rb
|
295
323
|
- spec/vcloud/fog/fog_model_interface_spec.rb
|
324
|
+
- spec/vcloud/fog/login_spec.rb
|
296
325
|
- spec/vcloud/fog/service_interface_spec.rb
|
326
|
+
- spec/vcloud/fog_spec.rb
|
data/tools/fog_credentials.rb
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# Initialiser for getting vCloud credentials into Fog from Jenkins build
|
2
|
-
# parameters, without needing to write them to disk. To be used with:
|
3
|
-
#
|
4
|
-
# RUBYOPT="-r ./tools/fog_credentials" bundle exec integration
|
5
|
-
#
|
6
|
-
# Replace with FOG_VCLOUD_TOKEN support when we have a tool:
|
7
|
-
#
|
8
|
-
# https://www.pivotaltracker.com/story/show/68989754
|
9
|
-
#
|
10
|
-
require 'bundler/setup'
|
11
|
-
require 'fog'
|
12
|
-
|
13
|
-
Fog.credentials = {
|
14
|
-
:vcloud_director_host => ENV['API_HOST'],
|
15
|
-
:vcloud_director_username => ENV['API_USERNAME'],
|
16
|
-
:vcloud_director_password => ENV['API_PASSWORD'],
|
17
|
-
}
|