admin-cf-plugin 0.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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,3 @@
1
+ require "admin-cf-plugin/curl"
2
+ require "admin-cf-plugin/guid"
3
+ require "admin-cf-plugin/service_auth_token"
@@ -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
@@ -0,0 +1,3 @@
1
+ module CFAdmin
2
+ VERSION = "0.2.0.rc1".freeze
3
+ 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
@@ -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