startapp 0.1.6

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.
Files changed (156) hide show
  1. checksums.yaml +7 -0
  2. data/COPYRIGHT +1 -0
  3. data/LICENSE +11 -0
  4. data/README.md +95 -0
  5. data/Rakefile +6 -0
  6. data/autocomplete/rhc_bash +1672 -0
  7. data/bin/app +37 -0
  8. data/conf/express.conf +8 -0
  9. data/features/assets/deploy.tar.gz +0 -0
  10. data/features/core_feature.rb +191 -0
  11. data/features/deployments_feature.rb +129 -0
  12. data/features/domains_feature.rb +58 -0
  13. data/features/keys_feature.rb +37 -0
  14. data/features/members_feature.rb +166 -0
  15. data/lib/rhc/auth/basic.rb +64 -0
  16. data/lib/rhc/auth/token.rb +102 -0
  17. data/lib/rhc/auth/token_store.rb +53 -0
  18. data/lib/rhc/auth.rb +5 -0
  19. data/lib/rhc/autocomplete.rb +66 -0
  20. data/lib/rhc/autocomplete_templates/bash.erb +39 -0
  21. data/lib/rhc/cartridge_helpers.rb +118 -0
  22. data/lib/rhc/cli.rb +40 -0
  23. data/lib/rhc/command_runner.rb +185 -0
  24. data/lib/rhc/commands/account.rb +25 -0
  25. data/lib/rhc/commands/alias.rb +124 -0
  26. data/lib/rhc/commands/app.rb +726 -0
  27. data/lib/rhc/commands/apps.rb +20 -0
  28. data/lib/rhc/commands/authorization.rb +115 -0
  29. data/lib/rhc/commands/base.rb +174 -0
  30. data/lib/rhc/commands/cartridge.rb +329 -0
  31. data/lib/rhc/commands/clone.rb +66 -0
  32. data/lib/rhc/commands/configure.rb +20 -0
  33. data/lib/rhc/commands/create.rb +100 -0
  34. data/lib/rhc/commands/delete.rb +19 -0
  35. data/lib/rhc/commands/deploy.rb +32 -0
  36. data/lib/rhc/commands/deployment.rb +82 -0
  37. data/lib/rhc/commands/domain.rb +172 -0
  38. data/lib/rhc/commands/env.rb +142 -0
  39. data/lib/rhc/commands/force_stop.rb +17 -0
  40. data/lib/rhc/commands/git_clone.rb +34 -0
  41. data/lib/rhc/commands/logout.rb +51 -0
  42. data/lib/rhc/commands/logs.rb +21 -0
  43. data/lib/rhc/commands/member.rb +148 -0
  44. data/lib/rhc/commands/port_forward.rb +197 -0
  45. data/lib/rhc/commands/reload.rb +17 -0
  46. data/lib/rhc/commands/restart.rb +17 -0
  47. data/lib/rhc/commands/scp.rb +54 -0
  48. data/lib/rhc/commands/server.rb +40 -0
  49. data/lib/rhc/commands/setup.rb +60 -0
  50. data/lib/rhc/commands/show.rb +43 -0
  51. data/lib/rhc/commands/snapshot.rb +137 -0
  52. data/lib/rhc/commands/ssh.rb +51 -0
  53. data/lib/rhc/commands/sshkey.rb +97 -0
  54. data/lib/rhc/commands/start.rb +17 -0
  55. data/lib/rhc/commands/stop.rb +17 -0
  56. data/lib/rhc/commands/tail.rb +47 -0
  57. data/lib/rhc/commands/threaddump.rb +14 -0
  58. data/lib/rhc/commands/tidy.rb +17 -0
  59. data/lib/rhc/commands.rb +396 -0
  60. data/lib/rhc/config.rb +321 -0
  61. data/lib/rhc/context_helper.rb +121 -0
  62. data/lib/rhc/core_ext.rb +202 -0
  63. data/lib/rhc/coverage_helper.rb +33 -0
  64. data/lib/rhc/deployment_helpers.rb +111 -0
  65. data/lib/rhc/exceptions.rb +256 -0
  66. data/lib/rhc/git_helpers.rb +106 -0
  67. data/lib/rhc/help_formatter.rb +55 -0
  68. data/lib/rhc/helpers.rb +481 -0
  69. data/lib/rhc/highline_extensions.rb +479 -0
  70. data/lib/rhc/json.rb +51 -0
  71. data/lib/rhc/output_helpers.rb +260 -0
  72. data/lib/rhc/rest/activation.rb +11 -0
  73. data/lib/rhc/rest/alias.rb +42 -0
  74. data/lib/rhc/rest/api.rb +87 -0
  75. data/lib/rhc/rest/application.rb +348 -0
  76. data/lib/rhc/rest/attributes.rb +36 -0
  77. data/lib/rhc/rest/authorization.rb +8 -0
  78. data/lib/rhc/rest/base.rb +79 -0
  79. data/lib/rhc/rest/cartridge.rb +162 -0
  80. data/lib/rhc/rest/client.rb +650 -0
  81. data/lib/rhc/rest/deployment.rb +18 -0
  82. data/lib/rhc/rest/domain.rb +98 -0
  83. data/lib/rhc/rest/environment_variable.rb +15 -0
  84. data/lib/rhc/rest/gear_group.rb +16 -0
  85. data/lib/rhc/rest/httpclient.rb +145 -0
  86. data/lib/rhc/rest/key.rb +44 -0
  87. data/lib/rhc/rest/membership.rb +105 -0
  88. data/lib/rhc/rest/mock.rb +1042 -0
  89. data/lib/rhc/rest/user.rb +32 -0
  90. data/lib/rhc/rest.rb +148 -0
  91. data/lib/rhc/scp_helpers.rb +27 -0
  92. data/lib/rhc/ssh_helpers.rb +380 -0
  93. data/lib/rhc/tar_gz.rb +51 -0
  94. data/lib/rhc/usage_templates/command_help.erb +51 -0
  95. data/lib/rhc/usage_templates/command_syntax_help.erb +11 -0
  96. data/lib/rhc/usage_templates/help.erb +61 -0
  97. data/lib/rhc/usage_templates/missing_help.erb +1 -0
  98. data/lib/rhc/usage_templates/options_help.erb +12 -0
  99. data/lib/rhc/vendor/okjson.rb +600 -0
  100. data/lib/rhc/vendor/parseconfig.rb +178 -0
  101. data/lib/rhc/vendor/sshkey.rb +253 -0
  102. data/lib/rhc/vendor/zliby.rb +628 -0
  103. data/lib/rhc/version.rb +5 -0
  104. data/lib/rhc/wizard.rb +637 -0
  105. data/lib/rhc.rb +34 -0
  106. data/spec/coverage_helper.rb +82 -0
  107. data/spec/direct_execution_helper.rb +339 -0
  108. data/spec/keys/example.pem +23 -0
  109. data/spec/keys/example_private.pem +27 -0
  110. data/spec/keys/server.pem +19 -0
  111. data/spec/rest_spec_helper.rb +31 -0
  112. data/spec/rhc/assets/cert.crt +22 -0
  113. data/spec/rhc/assets/cert_key_rsa +27 -0
  114. data/spec/rhc/assets/empty.txt +0 -0
  115. data/spec/rhc/assets/env_vars.txt +7 -0
  116. data/spec/rhc/assets/env_vars_2.txt +1 -0
  117. data/spec/rhc/assets/foo.txt +1 -0
  118. data/spec/rhc/assets/targz_corrupted.tar.gz +1 -0
  119. data/spec/rhc/assets/targz_sample.tar.gz +0 -0
  120. data/spec/rhc/auth_spec.rb +442 -0
  121. data/spec/rhc/cli_spec.rb +186 -0
  122. data/spec/rhc/command_spec.rb +435 -0
  123. data/spec/rhc/commands/account_spec.rb +42 -0
  124. data/spec/rhc/commands/alias_spec.rb +333 -0
  125. data/spec/rhc/commands/app_spec.rb +777 -0
  126. data/spec/rhc/commands/apps_spec.rb +39 -0
  127. data/spec/rhc/commands/authorization_spec.rb +157 -0
  128. data/spec/rhc/commands/cartridge_spec.rb +665 -0
  129. data/spec/rhc/commands/clone_spec.rb +41 -0
  130. data/spec/rhc/commands/deployment_spec.rb +327 -0
  131. data/spec/rhc/commands/domain_spec.rb +401 -0
  132. data/spec/rhc/commands/env_spec.rb +493 -0
  133. data/spec/rhc/commands/git_clone_spec.rb +102 -0
  134. data/spec/rhc/commands/logout_spec.rb +86 -0
  135. data/spec/rhc/commands/member_spec.rb +247 -0
  136. data/spec/rhc/commands/port_forward_spec.rb +217 -0
  137. data/spec/rhc/commands/scp_spec.rb +77 -0
  138. data/spec/rhc/commands/server_spec.rb +69 -0
  139. data/spec/rhc/commands/setup_spec.rb +118 -0
  140. data/spec/rhc/commands/snapshot_spec.rb +179 -0
  141. data/spec/rhc/commands/ssh_spec.rb +163 -0
  142. data/spec/rhc/commands/sshkey_spec.rb +188 -0
  143. data/spec/rhc/commands/tail_spec.rb +81 -0
  144. data/spec/rhc/commands/threaddump_spec.rb +84 -0
  145. data/spec/rhc/config_spec.rb +407 -0
  146. data/spec/rhc/helpers_spec.rb +531 -0
  147. data/spec/rhc/highline_extensions_spec.rb +314 -0
  148. data/spec/rhc/json_spec.rb +30 -0
  149. data/spec/rhc/rest_application_spec.rb +258 -0
  150. data/spec/rhc/rest_client_spec.rb +752 -0
  151. data/spec/rhc/rest_spec.rb +740 -0
  152. data/spec/rhc/targz_spec.rb +55 -0
  153. data/spec/rhc/wizard_spec.rb +756 -0
  154. data/spec/spec_helper.rb +575 -0
  155. data/spec/wizard_spec_helper.rb +330 -0
  156. metadata +469 -0
@@ -0,0 +1,98 @@
1
+ module RHC
2
+ module Rest
3
+ class Domain < Base
4
+ include Membership
5
+
6
+ define_attr :id, # Domain name for API version < 1.6, domain unique id otherwise
7
+ :name, # Available from API version 1.6 onwards
8
+ :allowed_gear_sizes, # Available from API version 1.3 onwards on compatible servers
9
+ :creation_time # Available from API version 1.3 onwards on compatible servers
10
+
11
+ def id
12
+ id_and_name.first
13
+ end
14
+ def name
15
+ id_and_name.last
16
+ end
17
+ def id_and_name
18
+ id = @id || attributes['id']
19
+ name = @name || attributes['name']
20
+ if name.present?
21
+ if id == name
22
+ [nil, name]
23
+ else
24
+ [id, name]
25
+ end
26
+ else
27
+ [nil, id]
28
+ end
29
+ end
30
+
31
+ #Add Application to this domain
32
+ # options
33
+ # cartridge
34
+ # template
35
+ # scale
36
+ # gear_profile
37
+ def add_application(name, options)
38
+ debug "Adding application #{name} to domain #{id}"
39
+
40
+ payload = {:name => name}
41
+ options.each{ |key, value| payload[key.to_sym] = value }
42
+
43
+ cartridges = Array(payload.delete(:cartridge)).concat(Array(payload.delete(:cartridges))).map do |cart|
44
+ if cart.is_a? String or cart.respond_to? :[]
45
+ cart
46
+ else
47
+ cart.url ? {:url => cart.url} : cart.name
48
+ end
49
+ end.compact.uniq
50
+
51
+ if cartridges.any?{ |c| c.is_a?(Hash) and c[:url] } and !has_param?('ADD_APPLICATION', 'cartridges[][url]')
52
+ raise RHC::Rest::DownloadingCartridgesNotSupported, "The server does not support downloading cartridges."
53
+ end
54
+
55
+ if client.api_version_negotiated >= 1.3
56
+ payload[:cartridges] = cartridges
57
+ else
58
+ raise RHC::Rest::MultipleCartridgeCreationNotSupported, "The server only supports creating an application with a single web cartridge." if cartridges.length > 1
59
+ payload[:cartridge] = cartridges.first
60
+ end
61
+
62
+ if payload[:initial_git_url] and !has_param?('ADD_APPLICATION', 'initial_git_url')
63
+ raise RHC::Rest::InitialGitUrlNotSupported, "The server does not support creating applications from a source repository."
64
+ end
65
+
66
+ options = {:timeout => options[:scale] && 0 || nil}
67
+ rest_method "ADD_APPLICATION", payload, options
68
+ end
69
+
70
+ def applications(options = {})
71
+ debug "Getting all applications for domain #{id}"
72
+ rest_method "LIST_APPLICATIONS", options
73
+ end
74
+
75
+ def rename(new_id)
76
+ debug "Updating domain #{id} to #{new_id}"
77
+ # 5 minute timeout as this may take time if there are a lot of apps
78
+ rest_method "UPDATE", {:id => new_id}, {:timeout => 0}
79
+ end
80
+ alias :update :rename
81
+
82
+ def configure(payload, options={})
83
+ self.attributes = rest_method("UPDATE", payload, options).attributes
84
+ self
85
+ end
86
+
87
+ def destroy(force=false)
88
+ debug "Deleting domain #{id}"
89
+ rest_method "DELETE", :force => force
90
+ end
91
+ alias :delete :destroy
92
+
93
+ def supports_add_application_with_env_vars?
94
+ has_param?('ADD_APPLICATION', 'environment_variables')
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,15 @@
1
+ module RHC
2
+ module Rest
3
+ class EnvironmentVariable < Base
4
+ define_attr :name, :value
5
+
6
+ def to_hash
7
+ { :name => name, :value => value }
8
+ end
9
+
10
+ def <=>(other)
11
+ name <=> other.name
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,16 @@
1
+ module RHC
2
+ module Rest
3
+ class GearGroup < Base
4
+ define_attr :gears, :cartridges, :gear_profile, :additional_gear_storage, :base_gear_storage
5
+
6
+ def name(gear)
7
+ gear['name'] ||= "#{group.cartridges.collect{ |c| c['name'] }.join('+')}:#{gear['id']}"
8
+ end
9
+
10
+ def quota
11
+ return nil unless base_gear_storage
12
+ ((additional_gear_storage || 0) + base_gear_storage) * 1024 * 1024 * 1024
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,145 @@
1
+ require 'httpclient'
2
+
3
+ class HTTPClient
4
+ class SSPINegotiateAuth
5
+ def get_with_rescue(*args)
6
+ get_without_rescue(*args)
7
+ rescue
8
+ unless @warned
9
+ @warned = true
10
+ RHC::Helpers.warn "Could not enable Kerberos authentication"
11
+ RHC::Helpers.warn $!.message.sub('gss_init_sec_context did not return GSS_S_COMPLETE: Unspecified GSS failure. Minor code may provide more information', '').strip rescue nil
12
+ end
13
+ nil
14
+ end
15
+
16
+ alias_method :get_without_rescue, :get if method_defined? :get
17
+ alias_method :get, :get_with_rescue
18
+ end
19
+ end
20
+
21
+ module RHC
22
+ module Rest
23
+ #
24
+ # An instance of HTTPClient that will support deferred
25
+ # Basic credentials and allow token challenges.
26
+ #
27
+ class HTTPClient < ::HTTPClient
28
+ def initialize(*args)
29
+ super
30
+ @www_auth = WWWAuth.new
31
+ @request_filter = [proxy_auth, www_auth]
32
+ end
33
+ end
34
+
35
+ #
36
+ # Support three altered authentication behaviors
37
+ #
38
+ # * Allow a bearer token to be provided for a server
39
+ # * Allow the user and password attributes to be lazily
40
+ # evaluated when the credentials are needed, rather than
41
+ # up front.
42
+ # * If a BASIC auth request has been rejected, do not
43
+ # retry.
44
+ #
45
+ class WWWAuth < HTTPClient::WWWAuth
46
+ attr_reader :oauth2
47
+ def initialize
48
+ super
49
+ @oauth2 = OAuth2.new
50
+ @authenticator.unshift(@oauth2)
51
+
52
+ deferred = DeferredBasic.new
53
+ @authenticator.map!{ |o| o == @basic_auth ? deferred : o }
54
+ @basic_auth = deferred
55
+ end
56
+
57
+ class OAuth2
58
+ include ::HTTPClient::Util
59
+ attr_reader :scheme
60
+
61
+ def initialize
62
+ @cred = nil
63
+ @auth = {}
64
+ @set = false
65
+ @scheme = "Bearer"
66
+ end
67
+
68
+ def reset_challenge
69
+ end
70
+
71
+ def set(uri, user, password)
72
+ @set = true
73
+ if uri.nil?
74
+ @cred = password
75
+ else
76
+ @auth[urify(uri)] = password
77
+ end
78
+ end
79
+
80
+ def set_token(uri, token)
81
+ set(uri, nil, token)
82
+ end
83
+
84
+ def set?
85
+ @set == true
86
+ end
87
+
88
+ def get(req)
89
+ target_uri = req.header.request_uri
90
+ return @cred if @cred
91
+ hash_find_value(@auth) { |uri, cred|
92
+ uri_part_of(target_uri, uri)
93
+ }
94
+ end
95
+
96
+ def challenge(uri, param_str = nil)
97
+ false
98
+ end
99
+ end
100
+
101
+ class DeferredCredential
102
+ def initialize(user, password)
103
+ @user, @password = user, password
104
+ end
105
+ def user
106
+ (@user.call if @user.respond_to?(:call)) or @user
107
+ end
108
+ def passwd
109
+ (@password.call if @password.respond_to?(:call)) or @password
110
+ end
111
+
112
+ #
113
+ # Pretend to be a string
114
+ #
115
+ def to_str
116
+ ["#{user}:#{passwd}"].pack('m').tr("\n", '')
117
+ end
118
+ [:sub].each do |sym|
119
+ define_method(sym) { |*args|; to_str.send(sym, *args); }
120
+ end
121
+ end
122
+
123
+ class DeferredBasic < ::HTTPClient::BasicAuth
124
+ # Set authentication credential.
125
+ # uri == nil for generic purpose (allow to use user/password for any URL).
126
+ def set(uri, user, passwd)
127
+ @set = true
128
+ if uri.nil?
129
+ @cred = DeferredCredential.new(user, passwd)
130
+ else
131
+ uri = uri_dirname(urify(uri))
132
+ @auth[uri] = DeferredCredential.new(user, passwd)
133
+ end
134
+ end
135
+ def challenge(uri, param_str = nil)
136
+ return false if caller.any?{ |s| s =~ /webmock.*httpclient_adapter.*build_request_signature/ }
137
+ uri = urify(uri)
138
+ challenged = @challengeable[uri]
139
+ @challengeable[uri] = true
140
+ !challenged
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,44 @@
1
+ module RHC
2
+ module Rest
3
+ class Key < Base
4
+ define_attr :name, :type, :content
5
+
6
+ def is_ssh?
7
+ type != 'krb5-principal'
8
+ end
9
+
10
+ def is_kerberos?
11
+ type == 'krb5-principal'
12
+ end
13
+
14
+ def update(type, content)
15
+ debug "Updating key #{self.name}"
16
+ rest_method "UPDATE", :type => type, :content => content
17
+ end
18
+
19
+ def destroy
20
+ debug "Deleting key #{self.name}"
21
+ rest_method "DELETE"
22
+ end
23
+ alias :delete :destroy
24
+
25
+ def principal
26
+ content if is_kerberos?
27
+ end
28
+
29
+ def fingerprint
30
+ @fingerprint ||= begin
31
+ public_key = Net::SSH::KeyFactory.load_data_public_key("#{type} #{content}")
32
+ public_key.fingerprint
33
+ rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
34
+ 'Invalid key'
35
+ end if is_ssh?
36
+ end
37
+
38
+ def visible_to_ssh?
39
+ is_ssh? and Net::SSH::Authentication::Agent.connect.identities.
40
+ find{ |i| fingerprint == i.fingerprint }.present? rescue false
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,105 @@
1
+ module RHC::Rest
2
+ module Membership
3
+ class Member < Base
4
+ define_attr :name, :login, :id, :type, :from, :role, :owner, :explicit_role
5
+ def owner?
6
+ !!owner
7
+ end
8
+ def admin?
9
+ role == 'admin'
10
+ end
11
+ def editor?
12
+ role == 'edit'
13
+ end
14
+ def viewer?
15
+ role == 'view'
16
+ end
17
+ def name
18
+ attributes['name'] || login
19
+ end
20
+ def to_s
21
+ if name == login
22
+ "#{login} (#{role})"
23
+ elsif login
24
+ "#{name} <#{login}> (#{role})"
25
+ else
26
+ "#{name} (#{role})"
27
+ end
28
+ end
29
+ def role_weight
30
+ case role
31
+ when 'admin' then 0
32
+ when 'edit' then 1
33
+ when 'view' then 2
34
+ else 3
35
+ end
36
+ end
37
+ end
38
+
39
+ def self.included(other)
40
+ end
41
+
42
+ def supports_members?
43
+ supports? 'LIST_MEMBERS'
44
+ end
45
+
46
+ def supports_update_members?
47
+ supports? 'UPDATE_MEMBERS'
48
+ end
49
+
50
+ def members
51
+ @members ||=
52
+ if (members = attributes['members']).nil?
53
+ debug "Getting all members for #{id}"
54
+ raise RHC::MembersNotSupported unless supports_members?
55
+ rest_method 'LIST_MEMBERS'
56
+ else
57
+ members.map{ |m| Member.new(m, client) }
58
+ end
59
+ end
60
+
61
+ def compact_members
62
+ arr = members.reject(&:owner?) rescue []
63
+ if arr.length > 5
64
+ arr = arr.sort_by(&:name)
65
+ admin, arr = arr.partition(&:admin?)
66
+ edit, arr = arr.partition(&:editor?)
67
+ view, arr = arr.partition(&:viewer?)
68
+ admin << "Admins" if admin.present?
69
+ edit << "Editors" if edit.present?
70
+ view << "Viewers" if view.present?
71
+ arr.map!(&:to_s)
72
+ admin.concat(edit).concat(view).concat(arr)
73
+ elsif arr.present?
74
+ arr.sort_by{ |m| [m.role_weight, m.name] }.join(', ')
75
+ end
76
+ end
77
+
78
+ def update_members(members, options={})
79
+ raise "Members must be an array" unless members.is_a?(Array)
80
+ raise RHC::MembersNotSupported unless supports_members?
81
+ raise RHC::ChangeMembersOnResourceNotSupported unless supports_update_members?
82
+ @members = (attributes['members'] = rest_method('UPDATE_MEMBERS', {:members => members}, options))
83
+ end
84
+
85
+ def delete_members(options={})
86
+ raise RHC::MembersNotSupported unless supports_members?
87
+ rest_method "LIST_MEMBERS", nil, {:method => :delete}.merge(options)
88
+ ensure
89
+ @members = attributes['members'] = nil
90
+ end
91
+
92
+ def leave(options={})
93
+ raise RHC::MembersNotSupported unless supports? 'LEAVE'
94
+ rest_method "LEAVE", nil, options
95
+ ensure
96
+ @members = attributes['members'] = nil
97
+ end
98
+
99
+ def owner
100
+ if o = Array(attributes['members']).find{ |m| m['owner'] == true }
101
+ o['name'] || o['login']
102
+ end
103
+ end
104
+ end
105
+ end