cf 5.0.0.rc1 → 5.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. data/lib/admin/plugin.rb +1 -0
  2. data/lib/admin/service_broker/add.rb +46 -0
  3. data/lib/cf/cli.rb +8 -3
  4. data/lib/cf/cli/service/create.rb +68 -20
  5. data/lib/cf/cli/service/delete.rb +1 -1
  6. data/lib/cf/cli/service/service_instance_helper.rb +99 -0
  7. data/lib/cf/cli/service/services.rb +12 -32
  8. data/lib/cf/cli/start/target.rb +1 -1
  9. data/lib/cf/version.rb +1 -1
  10. data/lib/manifests/manifests.rb +41 -25
  11. data/lib/tasks/gem_release.rake +1 -1
  12. data/spec/admin/service_broker/add_spec.rb +59 -0
  13. data/spec/assets/env/Gemfile +4 -0
  14. data/spec/assets/env/Gemfile.lock +20 -0
  15. data/spec/assets/env/env_test.rb +58 -0
  16. data/spec/cf/cli/app/delete_spec.rb +2 -2
  17. data/spec/cf/cli/app/push/create_spec.rb +1 -1
  18. data/spec/cf/cli/service/create_spec.rb +51 -4
  19. data/spec/cf/cli/service/rename_spec.rb +1 -1
  20. data/spec/cf/cli/service/service_instance_helper_spec.rb +155 -0
  21. data/spec/cf/cli/service/services_spec.rb +63 -34
  22. data/spec/cf/cli/space/space_spec.rb +1 -1
  23. data/spec/cf/cli/space/spaces_spec.rb +3 -3
  24. data/spec/factories/cfoundry/v2/{service_instances_factory.rb → managed_service_instances_factory.rb} +2 -2
  25. data/spec/factories/cfoundry/v2/user_provided_service_instances_factory.rb +12 -0
  26. data/spec/features/delete_orphaned_service_spec.rb +64 -0
  27. data/spec/features/manifests_spec.rb +86 -0
  28. data/spec/features/org_spec.rb +4 -4
  29. data/spec/{integration → features}/push_flow_spec.rb +27 -3
  30. data/spec/features/services_spec.rb +96 -0
  31. data/spec/integration/service_broker_spec.rb +49 -0
  32. data/spec/manifests/manifests_spec.rb +46 -25
  33. data/spec/spec_helper.rb +7 -1
  34. data/spec/support/features_helper.rb +36 -3
  35. data/spec/support/matchers.rb +14 -3
  36. metadata +109 -9
@@ -29,7 +29,7 @@ module CF
29
29
 
30
30
  let(:apps) { Array.new(2) { build(:app) } }
31
31
  let(:domains) { Array.new(2) { build(:domain) } }
32
- let(:services) { Array.new(2) { build(:service_instance) } }
32
+ let(:services) { Array.new(2) { build(:managed_service_instance) } }
33
33
  let(:space) { build(:space, :name => "some_space_name", :apps => apps, :service_instances => services, :domains => domains, :organization => organization ) }
34
34
  let(:spaces) { [space] }
35
35
  let(:organization) { build(:organization, :name => "Spacey Org") }
@@ -5,9 +5,9 @@ module CF
5
5
  describe Spaces do
6
6
  let(:full) { false }
7
7
  let(:app) { build(:app) }
8
- let!(:space_1) { build(:space, :name => "bb_second", :apps => [app], :service_instances => [build(:service_instance)]) }
9
- let!(:space_2) { build(:space, :name => "aa_first", :apps => [app], :service_instances => [build(:service_instance)], :domains => [build(:domain)]) }
10
- let!(:space_3) { build(:space, :name => "cc_last", :apps => [app], :service_instances => [build(:service_instance)], :domains => [build(:domain)]) }
8
+ let!(:space_1) { build(:space, :name => "bb_second", :apps => [app], :service_instances => [build(:managed_service_instance)]) }
9
+ let!(:space_2) { build(:space, :name => "aa_first", :apps => [app], :service_instances => [build(:managed_service_instance)], :domains => [build(:domain)]) }
10
+ let!(:space_3) { build(:space, :name => "cc_last", :apps => [app], :service_instances => [build(:managed_service_instance)], :domains => [build(:domain)]) }
11
11
  let(:spaces) { [space_1, space_2, space_3] }
12
12
  let(:organization) { build(:organization, :spaces => spaces, :name => "foo") }
13
13
  let(:client) do
@@ -1,5 +1,5 @@
1
1
  FactoryGirl.define do
2
- factory :service_instance, :class => CFoundry::V2::ServiceInstance do
2
+ factory :managed_service_instance, :class => CFoundry::V2::ManagedServiceInstance do
3
3
  sequence(:guid) { |n| "service-instance-guid-#{n}" }
4
4
  sequence(:name) { |n| "service-instance-name-#{n}" }
5
5
 
@@ -9,4 +9,4 @@ FactoryGirl.define do
9
9
 
10
10
  initialize_with { new(guid, client) }
11
11
  end
12
- end
12
+ end
@@ -0,0 +1,12 @@
1
+ FactoryGirl.define do
2
+ factory :user_provided_service_instance, :class => CFoundry::V2::UserProvidedServiceInstance do
3
+ sequence(:guid) { |n| "user-provided-service-instance-guid-#{n}" }
4
+ sequence(:name) { |n| "user-provided-service-instance-name-#{n}" }
5
+
6
+ ignore do
7
+ client { FactoryGirl.build(:client) }
8
+ end
9
+
10
+ initialize_with { new(guid, client) }
11
+ end
12
+ end
@@ -0,0 +1,64 @@
1
+ require "spec_helper"
2
+ require "webmock/rspec"
3
+
4
+ if ENV["CF_V2_RUN_INTEGRATION"]
5
+ describe "A user deleting an app bound to a user-provided service" do
6
+ let(:run_id) { TRAVIS_BUILD_ID.to_s + Time.new.to_f.to_s.gsub(".", "_") }
7
+ let(:app) { "hello-sinatra-#{run_id}" }
8
+ let(:user_provided_name) { "user-provided-#{run_id}"}
9
+
10
+ before do
11
+ FileUtils.rm_rf File.expand_path(CF::CONFIG_DIR)
12
+ WebMock.allow_net_connect!
13
+ login
14
+ end
15
+
16
+ after do
17
+ `#{cf_bin} unbind-service -f --no-script #{user_provided_name} #{app}`
18
+ `#{cf_bin} delete-service -f --no-script #{user_provided_name}`
19
+
20
+ `#{cf_bin} delete #{app} -f --routes --no-script`
21
+ logout
22
+ end
23
+
24
+ it "can delete the user-provided service when given --delete-orphaned" do
25
+ Dir.chdir("#{SPEC_ROOT}/assets/hello-sinatra") do
26
+ FileUtils.rm("manifest.yml", force: true)
27
+ File.open("manifest.yml", "w") do |f|
28
+ f.write(<<-MANIFEST)
29
+ ---
30
+ applications:
31
+ - name: #{app}
32
+ memory: 256M
33
+ instances: 1
34
+ host: ~
35
+ domain: none
36
+ path: .
37
+ services:
38
+ #{user_provided_name}:
39
+ label: user-provided
40
+ credentials:
41
+ username: abc123
42
+ MANIFEST
43
+ end
44
+
45
+ BlueShell::Runner.run("#{cf_bin} push --no-start") do |runner|
46
+ expect(runner).to say "Using manifest file manifest.yml"
47
+ expect(runner).to say "Creating #{app}... OK"
48
+
49
+ expect(runner).to say /Creating service #{user_provided_name}.*OK/
50
+ expect(runner).to say /Binding #{user_provided_name} to #{app}... OK/
51
+
52
+ expect(runner).to say "Uploading #{app}... OK"
53
+ end
54
+ end
55
+
56
+ BlueShell::Runner.run("#{cf_bin} delete #{app} --delete-orphaned --force") do |runner|
57
+ expect(runner).to say "Deleting #{app}... OK"
58
+ expect(runner).to say "Deleting #{user_provided_name}... OK"
59
+ end
60
+ end
61
+ end
62
+ else
63
+ $stderr.puts 'Skipping v2 integration specs; please provide necessary environment variables'
64
+ end
@@ -0,0 +1,86 @@
1
+ require "spec_helper"
2
+ require "webmock/rspec"
3
+
4
+ if ENV["CF_V2_RUN_INTEGRATION"]
5
+ describe "A user pushing a new sinatra app" do
6
+
7
+ let(:run_id) { TRAVIS_BUILD_ID.to_s + Time.new.to_f.to_s.gsub(".", "_") }
8
+ let(:app) { "hello-sinatra-#{run_id}" }
9
+ let(:subdomain) { "hello-sinatra-subdomain-#{run_id}" }
10
+ let(:user_provided_name) { "user-provided-#{run_id}"}
11
+
12
+ before do
13
+ FileUtils.rm_rf File.expand_path(CF::CONFIG_DIR)
14
+ WebMock.allow_net_connect!
15
+ login
16
+ end
17
+
18
+ after do
19
+ `#{cf_bin} unbind-service -f --no-script #{user_provided_name} #{app}`
20
+ `#{cf_bin} delete-service -f --no-script #{user_provided_name}`
21
+
22
+ `#{cf_bin} delete #{app} -f --routes --no-script`
23
+ logout
24
+ end
25
+
26
+ context "with user-provided service" do
27
+ it "reads the manifest when pushing" do
28
+ Dir.chdir("#{SPEC_ROOT}/assets/hello-sinatra") do
29
+ FileUtils.rm("manifest.yml", force: true)
30
+ File.open("manifest.yml", "w") do |f|
31
+ f.write(<<-MANIFEST)
32
+ ---
33
+ applications:
34
+ - name: #{app}
35
+ memory: 256M
36
+ instances: 1
37
+ host: #{subdomain}
38
+ domain: a1-app.cf-app.com
39
+ path: .
40
+ services:
41
+ #{user_provided_name}:
42
+ label: user-provided
43
+ credentials:
44
+ username: abc123
45
+ password: sunshine
46
+ hostname: oracle.enterprise.com
47
+ port: 1234
48
+ name: myoracledb2
49
+ MANIFEST
50
+ end
51
+
52
+ BlueShell::Runner.run("#{cf_bin} push") do |runner|
53
+ expect(runner).to say "Using manifest file manifest.yml"
54
+ expect(runner).to say "Creating #{app}... OK"
55
+
56
+ expect(runner).to say(/Creating route #{subdomain}\..*\.\.\. OK/)
57
+ expect(runner).to say(/Binding #{subdomain}\..* to #{app}\.\.\. OK/)
58
+
59
+ expect(runner).to say /Creating service #{user_provided_name}.*OK/
60
+ expect(runner).to say /Binding #{user_provided_name} to #{app}... OK/
61
+
62
+ expect(runner).to say "Uploading #{app}... OK", 180
63
+ expect(runner).to say "Preparing to start #{app}... OK", 180
64
+ expect(runner).to say "Checking status of app '#{app}'...", 180
65
+ expect(runner).to say "1 of 1 instances running"
66
+ expect(runner).to say "Push successful! App '#{app}' available at http://#{subdomain}.a1-app.cf-app.com", 30
67
+ end
68
+ end
69
+
70
+ BlueShell::Runner.run("#{cf_bin} services") do |runner|
71
+ expect(runner).to say /name\s+service\s+provider\s+version\s+plan\s+bound apps/
72
+ expect(runner).to say /#{user_provided_name}\s+ # name
73
+ user-provided\s+ # service
74
+ n\/a\s+ # provider
75
+ n\/a\s+ # version
76
+ n\/a\s+ # plan
77
+ #{app} # bound apps
78
+ /x
79
+ end
80
+ end
81
+ end
82
+
83
+ end
84
+ else
85
+ $stderr.puts 'Skipping v2 integration specs; please provide necessary environment variables'
86
+ end
@@ -24,13 +24,13 @@ if ENV["CF_V2_RUN_INTEGRATION"]
24
24
  end
25
25
 
26
26
  it "can create and recursively delete an org" do
27
- BlueShell::Runner.run("cf create-org #{new_org_name}") do |runner|
27
+ BlueShell::Runner.run("#{cf_bin} create-org #{new_org_name}") do |runner|
28
28
  runner.should say "Creating organization #{new_org_name}... OK"
29
29
  runner.should say "Switching to organization #{new_org_name}... OK"
30
30
  runner.should say "There are no spaces. You may want to create one with create-space."
31
31
  end
32
32
 
33
- BlueShell::Runner.run("cf create-space new-space") do |runner|
33
+ BlueShell::Runner.run("#{cf_bin} create-space new-space") do |runner|
34
34
  runner.should say "Creating space new-space... OK"
35
35
  end
36
36
 
@@ -39,11 +39,11 @@ if ENV["CF_V2_RUN_INTEGRATION"]
39
39
  # runner.should say "If you want to delete the organization along with all dependent objects, rerun the command with the '--recursive' flag."
40
40
  #end
41
41
 
42
- BlueShell::Runner.run("cf delete-org #{new_org_name} --force --recursive") do |runner|
42
+ BlueShell::Runner.run("#{cf_bin} delete-org #{new_org_name} --force --recursive") do |runner|
43
43
  runner.should say("Deleting organization #{new_org_name}... OK")
44
44
  end
45
45
 
46
- BlueShell::Runner.run("cf orgs") do |runner|
46
+ BlueShell::Runner.run("#{cf_bin} orgs") do |runner|
47
47
  runner.should_not say("#{new_org_name}")
48
48
  end
49
49
  end
@@ -3,12 +3,11 @@ require "webmock/rspec"
3
3
 
4
4
  if ENV["CF_V2_RUN_INTEGRATION"]
5
5
  describe "A user pushing a new sinatra app", :ruby19 => true do
6
- include CF::Interactive
7
-
8
6
  let(:run_id) { TRAVIS_BUILD_ID.to_s + Time.new.to_f.to_s.gsub(".", "_") }
9
7
  let(:app) { "hello-sinatra-#{run_id}" }
10
8
  let(:subdomain) { "hello-sinatra-subdomain-#{run_id}" }
11
9
  let(:service_name) { "dummy-service-#{run_id}" }
10
+ let(:user_provided_name) { "user-provided-#{run_id}"}
12
11
 
13
12
  before do
14
13
  FileUtils.rm_rf File.expand_path(CF::CONFIG_DIR)
@@ -20,6 +19,10 @@ if ENV["CF_V2_RUN_INTEGRATION"]
20
19
  after do
21
20
  `#{cf_bin} unbind-service -f --no-script #{service_name} #{app}`
22
21
  `#{cf_bin} delete-service -f --no-script #{service_name}`
22
+
23
+ `#{cf_bin} unbind-service -f --no-script #{user_provided_name} #{app}`
24
+ `#{cf_bin} delete-service -f --no-script #{user_provided_name}`
25
+
23
26
  `#{cf_bin} delete #{app} -f --routes --no-script`
24
27
  logout
25
28
  Interact::Progress::Dots.stop!
@@ -31,6 +34,7 @@ if ENV["CF_V2_RUN_INTEGRATION"]
31
34
  end
32
35
 
33
36
  Dir.chdir("#{SPEC_ROOT}/assets/hello-sinatra") do
37
+ FileUtils.rm("manifest.yml", force: true)
34
38
  BlueShell::Runner.run("#{cf_bin} push") do |runner|
35
39
  expect(runner).to say "Name>"
36
40
  runner.send_keys app
@@ -85,7 +89,27 @@ if ENV["CF_V2_RUN_INTEGRATION"]
85
89
  expect(runner).not_to say "Which plan?>"
86
90
  runner.send_up_arrow
87
91
  expect(runner).not_to say "Which plan?>"
88
- runner.send_return
92
+ runner.send_keys "y"
93
+
94
+ # create a user-provided service here
95
+ expect(runner).to say "What kind?>"
96
+ runner.send_keys "user-provided"
97
+
98
+ expect(runner).to say "Name?>"
99
+ runner.send_keys user_provided_name
100
+
101
+ expect(runner).not_to say "Which plan?>"
102
+ expect(runner).to say "What credential parameters should applications use to connect to this service instance?\n(e.g. hostname, port, password)>"
103
+ runner.send_keys "uri"
104
+
105
+ expect(runner).to say "uri>"
106
+ runner.send_keys "mysql://u:p@example.com:port/db"
107
+
108
+ expect(runner).to say /Creating service #{user_provided_name}.*OK/
109
+ expect(runner).to say /Binding .+ to .+ OK/
110
+
111
+ expect(runner).to say "Create another service?> n"
112
+ runner.send_keys "n"
89
113
 
90
114
  if runner.expect "Bind other services to application?> n", 15
91
115
  runner.send_return
@@ -6,6 +6,25 @@ if ENV['CF_V2_RUN_INTEGRATION']
6
6
  login
7
7
  end
8
8
 
9
+ describe "listing services" do
10
+ let(:service1) { "some-provided-instance-#{Time.now.to_i}" }
11
+ let(:service2) { "cf-managed-instance-#{Time.now.to_i}" }
12
+
13
+ it "shows all service instances in the space" do
14
+ create_service_instance("user-provided", service1, credentials: { hostname: "myservice.com"} )
15
+ create_service_instance("dummy-dev", service2, plan: "small")
16
+
17
+ BlueShell::Runner.run("#{cf_bin} services") do |runner|
18
+ expect(runner).to say /#{service1}\s+user-provided\s+n\/a\s+n\/a\s+n\/a\s+.*/
19
+ end
20
+ end
21
+
22
+ after do
23
+ delete_service(service1)
24
+ delete_service(service2)
25
+ end
26
+ end
27
+
9
28
  describe "creating a service" do
10
29
  describe "when the user leaves the line blank for a plan" do
11
30
  it "re-prompts for the plan" do
@@ -20,6 +39,83 @@ if ENV['CF_V2_RUN_INTEGRATION']
20
39
  end
21
40
  end
22
41
  end
42
+
43
+ describe "when the service is a user-provided instance" do
44
+ let(:service_name) { "my-private-db-#{Random.rand(1000) + 1000}"}
45
+
46
+ it "can create a service instance" do
47
+ BlueShell::Runner.run("#{cf_bin} create-service") do |runner|
48
+ expect(runner).to say "What kind?"
49
+ runner.send_keys "user-provided"
50
+
51
+ expect(runner).to say "Name?"
52
+ runner.send_keys service_name
53
+
54
+ expect(runner).to say "What credential parameters should applications use to connect to this service instance?\n(e.g. hostname, port, password)"
55
+ runner.send_keys "hostname"
56
+ expect(runner).to say "hostname"
57
+ runner.send_keys "myserviceinstance.com"
58
+
59
+ expect(runner).to say /Creating service #{service_name}.+ OK/
60
+ end
61
+ end
62
+
63
+ after do
64
+ delete_service(service_name)
65
+ end
66
+ end
67
+ end
68
+
69
+ describe "binding to a service" do
70
+ let(:app_folder) { "env" }
71
+ let(:app_name) { "services_env_test_app-#{Time.now.to_i}" }
72
+
73
+ let(:service_name) { "some-provided-instance-#{Time.now.to_i}" }
74
+
75
+ it "can bind and unbind user-provided services to apps" do
76
+ push_app(app_folder, app_name, start_command: "'bundle exec ruby env_test.rb -p $PORT'", timeout: 90)
77
+ create_service_instance("user-provided", service_name, credentials: { hostname: "myservice.com"} )
78
+
79
+ BlueShell::Runner.run("#{cf_bin} bind-service") do |runner|
80
+ expect(runner).to say "Which application?>"
81
+ runner.send_keys app_name
82
+
83
+ expect(runner).to say "Which service?>"
84
+ runner.send_keys service_name
85
+
86
+ expect(runner).to say "Binding #{service_name} to #{app_name}... OK"
87
+ end
88
+
89
+ BlueShell::Runner.run("#{cf_bin} unbind-service") do |runner|
90
+ expect(runner).to say "Which application?"
91
+ runner.send_keys app_name
92
+
93
+ expect(runner).to say "Which service?>"
94
+ runner.send_keys service_name
95
+
96
+ expect(runner).to say "Unbinding #{service_name} from #{app_name}... OK"
97
+ end
98
+ end
99
+
100
+ after do
101
+ delete_app(app_name)
102
+ end
103
+ end
104
+
105
+ def delete_service(service_name)
106
+ BlueShell::Runner.run("#{cf_bin} delete-service --service #{service_name} --force") do |runner|
107
+ expect(runner).to say "Deleting #{service_name}... OK"
108
+ end
109
+ end
110
+
111
+ def delete_app(app_name, routes=true)
112
+ delete_cmd = "#{cf_bin} delete #{app_name}"
113
+ delete_cmd + " --routes" if routes
114
+ BlueShell::Runner.run(delete_cmd) do |runner|
115
+ expect(runner).to say "Really delete #{app_name}?"
116
+ runner.send_keys "y"
117
+ expect(runner).to say "Deleting #{app_name}... OK"
118
+ end
23
119
  end
24
120
  end
25
121
  end
@@ -0,0 +1,49 @@
1
+ require "spec_helper"
2
+
3
+ describe "Service Broker Management", components: [:nats, :uaa, :ccng] do
4
+ let(:username) { 'admin' }
5
+ let(:password) { 'the_admin_pw' }
6
+ let(:target) { 'http://127.0.0.1:8181' }
7
+
8
+ before do
9
+ create_user_in_ccng
10
+ logout
11
+ end
12
+
13
+ after do
14
+ logout
15
+ end
16
+
17
+ it "allows an admin user to add a service broker" do
18
+ BlueShell::Runner.run("#{cf_bin} target #{target}") do |runner|
19
+ runner.wait_for_exit
20
+
21
+ expect(runner).to be_successful
22
+ end
23
+
24
+ BlueShell::Runner.run("#{cf_bin} login #{username} --password #{password}") do |runner|
25
+ expect(runner).to say "Authenticating... OK"
26
+ end
27
+
28
+ BlueShell::Runner.run("#{cf_bin} add-service-broker --name cf-mysql --url http://cf-mysql.cfapp.io --token cfmysqlsecret") do |runner|
29
+ expect(runner).to say "... OK"
30
+ end
31
+ end
32
+
33
+ def create_user_in_ccng
34
+ ccng_post "/v2/users", {
35
+ guid: user_guid
36
+ }
37
+ end
38
+
39
+ def user_guid
40
+ uaa_port = component!(:uaa).port
41
+ token_issuer = CF::UAA::TokenIssuer.new("http://localhost:#{uaa_port}", 'cf')
42
+ auth_header = token_issuer.owner_password_grant(username, password).auth_header
43
+ response = Typhoeus::Request.new(
44
+ "http://localhost:#{uaa_port}/Users?filter=userName+eq+'#{username}'",
45
+ headers: {'Authorization' => auth_header}
46
+ ).run
47
+ JSON.parse(response.body).fetch("resources").first.fetch('id')
48
+ end
49
+ end