admin-cf-plugin 0.2.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.
- data/Rakefile +38 -0
- data/lib/admin-cf-plugin/curl.rb +56 -0
- data/lib/admin-cf-plugin/guid.rb +89 -0
- data/lib/admin-cf-plugin/plugin.rb +3 -0
- data/lib/admin-cf-plugin/service_auth_token.rb +93 -0
- data/lib/admin-cf-plugin/version.rb +3 -0
- data/spec/curl_spec.rb +46 -0
- data/spec/guid_spec.rb +87 -0
- data/spec/spec_helper.rb +18 -0
- metadata +95 -0
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
|
5
|
+
require "admin-cf-plugin/version"
|
6
|
+
|
7
|
+
RSpec::Core::RakeTask.new(:spec)
|
8
|
+
task :default => :spec
|
9
|
+
|
10
|
+
namespace :deploy do
|
11
|
+
def last_staging_sha
|
12
|
+
`git rev-parse latest-staging`.strip
|
13
|
+
end
|
14
|
+
|
15
|
+
def last_release_sha
|
16
|
+
`git rev-parse latest-release`.strip
|
17
|
+
end
|
18
|
+
|
19
|
+
def last_staging_ref_was_released?
|
20
|
+
last_staging_sha == last_release_sha
|
21
|
+
end
|
22
|
+
|
23
|
+
task :staging, :version do |_, args|
|
24
|
+
sh "gem bump --push #{"--version #{args.version}" if args.version}" if last_staging_ref_was_released?
|
25
|
+
sh "git tag -f latest-staging"
|
26
|
+
sh "git push origin :latest-staging"
|
27
|
+
sh "git push origin latest-staging"
|
28
|
+
end
|
29
|
+
|
30
|
+
task :gem do
|
31
|
+
sh "git fetch"
|
32
|
+
sh "git checkout #{last_staging_sha}"
|
33
|
+
sh "gem release --tag"
|
34
|
+
sh "git tag -f latest-release"
|
35
|
+
sh "git push origin :latest-release"
|
36
|
+
sh "git push origin latest-release"
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "cf/cli"
|
2
|
+
|
3
|
+
module CFAdmin
|
4
|
+
class Curl < CF::CLI
|
5
|
+
def precondition
|
6
|
+
check_target
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Execute a raw request"
|
10
|
+
group :admin
|
11
|
+
input :mode, :argument => :required,
|
12
|
+
:desc => "Request mode (Get/Put/etc.)"
|
13
|
+
input :path, :argument => :required,
|
14
|
+
:desc => "Request path"
|
15
|
+
input :headers, :argument => :splat,
|
16
|
+
:desc => "Headers (i.e. Foo: bar)"
|
17
|
+
input :body, :alias => "-b",
|
18
|
+
:desc => "Request body"
|
19
|
+
def curl
|
20
|
+
mode = input[:mode].upcase
|
21
|
+
path = input[:path]
|
22
|
+
body = input[:body]
|
23
|
+
|
24
|
+
headers = {}
|
25
|
+
input[:headers].each do |h|
|
26
|
+
k, v = h.split(/\s*:\s*/, 2)
|
27
|
+
headers[k.downcase] = v
|
28
|
+
end
|
29
|
+
|
30
|
+
content = headers["content-type"]
|
31
|
+
accept = headers["accept"]
|
32
|
+
|
33
|
+
content ||= :json if body
|
34
|
+
accept ||= :json unless %w(DELETE HEAD).include?(mode)
|
35
|
+
|
36
|
+
req, res =
|
37
|
+
client.base.rest_client.request(
|
38
|
+
mode,
|
39
|
+
remove_leading_slash(path),
|
40
|
+
:headers => headers,
|
41
|
+
:accept => accept,
|
42
|
+
:payload => body,
|
43
|
+
:content => body && content)
|
44
|
+
|
45
|
+
if [:json, "application/json"].include? accept
|
46
|
+
puts MultiJson.dump(res, :pretty => true)
|
47
|
+
else
|
48
|
+
puts res
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def remove_leading_slash(path)
|
53
|
+
path.sub(%r{^/}, '')
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require "cf/cli"
|
2
|
+
|
3
|
+
module CFAdmin
|
4
|
+
class Guid < CF::CLI
|
5
|
+
def precondition
|
6
|
+
check_target
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "Obtain guid of an object(s)"
|
10
|
+
group :admin
|
11
|
+
input :type, :argument => :required, :desc => "Object type (e.g. org, space, app, domain, ...)"
|
12
|
+
input :name, :argument => :optional, :desc => "Object name (e.g. some-app, ...)"
|
13
|
+
def guid
|
14
|
+
type = expand_type(input[:type])
|
15
|
+
name = input[:name]
|
16
|
+
|
17
|
+
_, res = client.base.rest_client.request("GET", api_path(type, name))
|
18
|
+
|
19
|
+
puts "Listing #{type} for '#{name}'...\n\n"
|
20
|
+
puts_response(res[:body])
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def api_path(type, name)
|
26
|
+
"".tap do |url|
|
27
|
+
url << "v2/#{type}?"
|
28
|
+
url << "q=name:#{name}" if name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
EXPANDED_TYPES = %w(
|
33
|
+
organizations
|
34
|
+
spaces
|
35
|
+
domains
|
36
|
+
routes
|
37
|
+
apps
|
38
|
+
services
|
39
|
+
service_instances
|
40
|
+
users
|
41
|
+
)
|
42
|
+
|
43
|
+
def expand_type(type)
|
44
|
+
EXPANDED_TYPES.detect do |expanded_type|
|
45
|
+
expanded_type.start_with?(type)
|
46
|
+
end || type
|
47
|
+
end
|
48
|
+
|
49
|
+
def puts_response(body)
|
50
|
+
# passing nil to load causes segfault
|
51
|
+
hash = MultiJson.load(body || "{}") rescue {}
|
52
|
+
|
53
|
+
puts_pagination(*hash.values_at("total_results", "total_pages"))
|
54
|
+
puts_resources(hash["resources"])
|
55
|
+
end
|
56
|
+
|
57
|
+
def puts_pagination(results, pages)
|
58
|
+
if results.nil?
|
59
|
+
puts "Unexpected response."
|
60
|
+
elsif results == 0
|
61
|
+
puts "No results."
|
62
|
+
else
|
63
|
+
puts "Found #{results} results on #{pages} pages. First page:"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def puts_resources(resources)
|
68
|
+
resources ||= []
|
69
|
+
|
70
|
+
sorted_resources = \
|
71
|
+
resources.sort_by { |r| [r["entity"]["name"].downcase] }
|
72
|
+
|
73
|
+
max_name_size = \
|
74
|
+
resources.map { |r| r["entity"]["name"].size }.max
|
75
|
+
|
76
|
+
sorted_resources.each_with_index do |resource, i|
|
77
|
+
puts_resource(resource, :max_name_size => max_name_size)
|
78
|
+
puts "---" if i % 3 == 2
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def puts_resource(resource, opts={})
|
83
|
+
puts [
|
84
|
+
resource["entity"]["name"].ljust(opts[:max_name_size] + 2),
|
85
|
+
resource["metadata"]["guid"],
|
86
|
+
].join
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require "cf/cli"
|
2
|
+
|
3
|
+
module CFAdmin
|
4
|
+
class ServiceAuthToken < CF::CLI
|
5
|
+
def precondition
|
6
|
+
unless File.exists? target_file
|
7
|
+
fail "Please select a target with 'cf target'."
|
8
|
+
end
|
9
|
+
|
10
|
+
unless client.logged_in?
|
11
|
+
fail "Please log in with 'cf login'."
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
desc "List service auth tokens"
|
17
|
+
group :admin
|
18
|
+
def service_auth_tokens
|
19
|
+
spaced(client.service_auth_tokens) do |t|
|
20
|
+
line "#{c(t.label, :name)}:"
|
21
|
+
|
22
|
+
indented do
|
23
|
+
line "guid: #{t.guid}"
|
24
|
+
line "provider: #{t.provider}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
desc "Create a service auth token"
|
31
|
+
group :admin
|
32
|
+
input(:label, :argument => :optional, :desc => "Auth token label") {
|
33
|
+
ask("Label")
|
34
|
+
}
|
35
|
+
input :provider, :argument => :optional, :default => "core",
|
36
|
+
:desc => "Auth token provider"
|
37
|
+
input(:token, :desc => "Auth token value") {
|
38
|
+
ask("Token")
|
39
|
+
}
|
40
|
+
def create_service_auth_token
|
41
|
+
sat = client.service_auth_token
|
42
|
+
sat.label = input[:label]
|
43
|
+
sat.provider = input[:provider]
|
44
|
+
sat.token = input[:token]
|
45
|
+
|
46
|
+
with_progress("Creating service auth token") do
|
47
|
+
sat.create!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
desc "Update a service auth token"
|
53
|
+
group :admin
|
54
|
+
input(:service_auth_token, :argument => :optional,
|
55
|
+
:from_given => proc { |guid| client.service_auth_token(guid) },
|
56
|
+
:desc => "Auth token to delete") {
|
57
|
+
tokens = client.service_auth_tokens
|
58
|
+
fail "No tokens!" if tokens.empty?
|
59
|
+
|
60
|
+
ask("Which token?", :choices => tokens, :display => proc(&:label))
|
61
|
+
}
|
62
|
+
input(:token, :desc => "Auth token value") {
|
63
|
+
ask("Token")
|
64
|
+
}
|
65
|
+
def update_service_auth_token
|
66
|
+
sat = input[:service_auth_token]
|
67
|
+
sat.token = input[:token]
|
68
|
+
|
69
|
+
with_progress("Updating token #{c(sat.label, :name)}") do
|
70
|
+
sat.update!
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
desc "Delete a service auth token"
|
76
|
+
group :admin
|
77
|
+
input(:service_auth_token, :argument => :optional,
|
78
|
+
:from_given => proc { |guid| client.service_auth_token(guid) },
|
79
|
+
:desc => "Auth token to delete") {
|
80
|
+
tokens = client.service_auth_tokens
|
81
|
+
fail "No tokens!" if tokens.empty?
|
82
|
+
|
83
|
+
ask("Which token?", :choices => tokens, :display => proc(&:label))
|
84
|
+
}
|
85
|
+
def delete_service_auth_token
|
86
|
+
sat = input[:service_auth_token]
|
87
|
+
|
88
|
+
with_progress("Deleting token #{c(sat.label, :name)}") do
|
89
|
+
sat.delete!
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/spec/curl_spec.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe CFAdmin::Curl do
|
4
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dir" }
|
5
|
+
stub_home_dir_with { fake_home_dir }
|
6
|
+
|
7
|
+
subject { cf ["curl", "--mode", "GET", "--path", path] }
|
8
|
+
|
9
|
+
before do
|
10
|
+
any_instance_of(CFoundry::Client) do |client|
|
11
|
+
stub(client).info { { :version => 2 } }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with an implicit target" do
|
16
|
+
let(:path) { "apps/5/instances" }
|
17
|
+
|
18
|
+
it "makes a request to the current target" do
|
19
|
+
stub_request(:get, "https://api.some-target-for-cf-curl.com/apps/5/instances").to_return(
|
20
|
+
:status => 200,
|
21
|
+
:body => 'some-body'
|
22
|
+
)
|
23
|
+
|
24
|
+
subject
|
25
|
+
|
26
|
+
expect(stdout.string).to include('"status": "200"')
|
27
|
+
expect(stdout.string).to include('"body": "some-body"')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context "with an explicit target" do
|
32
|
+
let(:path) { "https://example.com/apps/5/instances" }
|
33
|
+
|
34
|
+
it "makes a request to the given target" do
|
35
|
+
stub_request(:get, "https://example.com/apps/5/instances").to_return(
|
36
|
+
:status => 200,
|
37
|
+
:body => 'some-other-body'
|
38
|
+
)
|
39
|
+
|
40
|
+
subject
|
41
|
+
|
42
|
+
expect(stdout.string).to include('"status": "200"')
|
43
|
+
expect(stdout.string).to include('"body": "some-other-body"')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/spec/guid_spec.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe CFAdmin::Guid do
|
4
|
+
let(:fake_home_dir) { "#{SPEC_ROOT}/fixtures/fake_home_dir" }
|
5
|
+
stub_home_dir_with { fake_home_dir }
|
6
|
+
|
7
|
+
before do
|
8
|
+
any_instance_of(CFoundry::Client) do |client|
|
9
|
+
stub(client).info { { :version => 2 } }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:api_response) {{
|
14
|
+
:total_results => 1,
|
15
|
+
:total_pages => 1,
|
16
|
+
:resources => [
|
17
|
+
:metadata => {
|
18
|
+
:guid => "guid",
|
19
|
+
},
|
20
|
+
:entity => {
|
21
|
+
:name => "name",
|
22
|
+
},
|
23
|
+
]
|
24
|
+
}}
|
25
|
+
|
26
|
+
def stub_api(path, response, opts={})
|
27
|
+
stub = stub_request(:get, "https://api.some-target-for-cf-curl.com#{path}")
|
28
|
+
response = MultiJson.dump(response) unless opts[:not_json]
|
29
|
+
stub.to_return(:status => 200, :body => response)
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when api returns >0 resources" do
|
33
|
+
context "with known type" do
|
34
|
+
let(:args) { ["guid", "--type", "organizations"] }
|
35
|
+
|
36
|
+
it "shows results" do
|
37
|
+
stub_api("/v2/organizations?", api_response)
|
38
|
+
cf(args)
|
39
|
+
expect(stdout.string).to match(/name.*guid/)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
context "with short known type" do
|
44
|
+
let(:args) { ["guid", "--type", "or"] }
|
45
|
+
|
46
|
+
it "shows results" do
|
47
|
+
stub_api("/v2/organizations?", api_response)
|
48
|
+
cf(args)
|
49
|
+
expect(stdout.string).to match(/name.*guid/)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "with unknown type" do
|
54
|
+
let(:args) { ["guid", "--type", "some-unknown-type"] }
|
55
|
+
|
56
|
+
it "makes a request with unknown type" do
|
57
|
+
stub_api("/v2/some-unknown-type?", api_response)
|
58
|
+
cf(args)
|
59
|
+
expect(stdout.string).to match(/name.*guid/)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when api returns 0 resources" do
|
65
|
+
before do
|
66
|
+
api_response[:total_results] = 0
|
67
|
+
api_response[:total_pages] = 0
|
68
|
+
api_response[:resources] = []
|
69
|
+
end
|
70
|
+
|
71
|
+
it "shows 0 results" do
|
72
|
+
stub_api("/v2/organizations?", api_response)
|
73
|
+
cf(["guid", "--type", "organizations"])
|
74
|
+
expect(stdout.string).to match(/No results/)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context "when api does not return resources (errors, etc.)" do
|
79
|
+
["", "not-json"].each do |response|
|
80
|
+
it "shows unexpected response for api resonse '#{response}'" do
|
81
|
+
stub_api("/v2/organizations?", response, :not_json => true)
|
82
|
+
cf(["guid", "--type", "organizations"])
|
83
|
+
expect(stdout.string).to match(/Unexpected response/)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
SPEC_ROOT = File.dirname(__FILE__).freeze
|
2
|
+
|
3
|
+
require "rspec"
|
4
|
+
require "cf"
|
5
|
+
require "cfoundry"
|
6
|
+
require "cfoundry/test_support"
|
7
|
+
require "webmock/rspec"
|
8
|
+
require "cf/test_support"
|
9
|
+
|
10
|
+
require "#{SPEC_ROOT}/../lib/admin-cf-plugin/plugin"
|
11
|
+
|
12
|
+
RSpec.configure do |c|
|
13
|
+
c.include Fake::FakeMethods
|
14
|
+
c.mock_with :rr
|
15
|
+
|
16
|
+
c.include FakeHomeDir
|
17
|
+
c.include CommandHelper
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: admin-cf-plugin
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 3583608865
|
5
|
+
prerelease: 6
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
- rc
|
11
|
+
- 1
|
12
|
+
version: 0.2.0.rc1
|
13
|
+
platform: ruby
|
14
|
+
authors:
|
15
|
+
- Alex Suraci
|
16
|
+
autorequire:
|
17
|
+
bindir: bin
|
18
|
+
cert_chain: []
|
19
|
+
|
20
|
+
date: 2013-03-18 00:00:00 Z
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: cfoundry
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ~>
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 11
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
- 5
|
34
|
+
- 0
|
35
|
+
version: 0.5.0
|
36
|
+
type: :runtime
|
37
|
+
version_requirements: *id001
|
38
|
+
description:
|
39
|
+
email:
|
40
|
+
- asuraci@vmware.com
|
41
|
+
executables: []
|
42
|
+
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
extra_rdoc_files: []
|
46
|
+
|
47
|
+
files:
|
48
|
+
- Rakefile
|
49
|
+
- lib/admin-cf-plugin/curl.rb
|
50
|
+
- lib/admin-cf-plugin/guid.rb
|
51
|
+
- lib/admin-cf-plugin/plugin.rb
|
52
|
+
- lib/admin-cf-plugin/service_auth_token.rb
|
53
|
+
- lib/admin-cf-plugin/version.rb
|
54
|
+
- spec/curl_spec.rb
|
55
|
+
- spec/guid_spec.rb
|
56
|
+
- spec/spec_helper.rb
|
57
|
+
homepage: http://cloudfoundry.com/
|
58
|
+
licenses: []
|
59
|
+
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
hash: 3
|
71
|
+
segments:
|
72
|
+
- 0
|
73
|
+
version: "0"
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ">"
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
hash: 25
|
80
|
+
segments:
|
81
|
+
- 1
|
82
|
+
- 3
|
83
|
+
- 1
|
84
|
+
version: 1.3.1
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project: admin-cf-plugin
|
88
|
+
rubygems_version: 1.8.24
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Cloud Foundry administration commands.
|
92
|
+
test_files:
|
93
|
+
- spec/curl_spec.rb
|
94
|
+
- spec/guid_spec.rb
|
95
|
+
- spec/spec_helper.rb
|