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,34 @@
1
+ require 'rhc/commands/base'
2
+ require 'rhc/git_helpers'
3
+
4
+ module RHC::Commands
5
+ class GitClone < Base
6
+ summary "Clone and configure an application's repository locally"
7
+ description "This is a convenience wrapper for 'git clone' with the added",
8
+ "benefit of adding configuration data such as the application's",
9
+ "UUID to the local repository. It also automatically",
10
+ "figures out the Git url from the application name so you don't",
11
+ "have to look it up."
12
+ syntax "<app> [--namespace NAME]"
13
+ takes_application :argument => true
14
+ option ["-r", "--repo dir"], "Path to the Git repository (defaults to ./$app_name)"
15
+ alias_action 'app git-clone', :deprecated => true, :root_command => true
16
+ # TODO: Implement default values for arguments once ffranz has added context arguments
17
+ # argument :directory, "The name of a new directory to clone into", [], :default => nil
18
+ def run(app_name)
19
+ if has_git?
20
+ rest_app = find_app
21
+ dir = git_clone_application(rest_app)
22
+ success "Your application Git repository has been cloned to '#{system_path(dir)}'"
23
+
24
+ 0
25
+ else
26
+ error "You do not have git installed. In order to fully interact with StartApp you will need to install and configure a git client."
27
+ 2
28
+ end
29
+ end
30
+
31
+ private
32
+ include RHC::GitHelpers
33
+ end
34
+ end
@@ -0,0 +1,51 @@
1
+ module RHC::Commands
2
+ class Logout < Base
3
+ suppress_wizard
4
+
5
+ summary "End the current session"
6
+ description <<-DESC
7
+ Logout ends your current session on the server and then removes
8
+ all of the local session files. If you are using multiple
9
+ servers and configurations this will remove all of your local
10
+ session files.
11
+
12
+ The --all option will terminate all authorizations on your
13
+ account. Any previously generated authorizations will be
14
+ deleted and external tools that integrate with your account
15
+ will no longer be able to log in.
16
+ DESC
17
+ option '--all', "Remove all authorizations on your account."
18
+ alias_action 'account logout', :root_command => true
19
+ def run
20
+ if options.all
21
+ rest_client.user # force authentication
22
+ say "Deleting all authorizations associated with your account ... "
23
+ begin
24
+ rest_client.delete_authorizations
25
+ success "done"
26
+ rescue RHC::Rest::AuthorizationsNotSupported
27
+ info "not supported"
28
+ end
29
+ elsif token_for_user
30
+ options.noprompt = true
31
+ say "Ending session on server ... "
32
+ begin
33
+ rest_client.delete_authorization(token_for_user)
34
+ success "deleted"
35
+ rescue RHC::Rest::AuthorizationsNotSupported
36
+ info "not supported"
37
+ rescue RHC::Rest::TokenExpiredOrInvalid
38
+ info "already closed"
39
+ rescue => e
40
+ debug_error(e)
41
+ warn e.message
42
+ end
43
+ end
44
+
45
+ 0
46
+ ensure
47
+ token_store.clear
48
+ success "All local sessions removed."
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,21 @@
1
+ require 'rhc/commands/tail'
2
+
3
+ module RHC::Commands
4
+ class Logs < Tail
5
+
6
+ summary "Tail the logs of an application"
7
+ syntax "<application>"
8
+ takes_application :argument => true
9
+ option ["-o", "--opts options"], "Options to pass to the server-side (linux based) tail command (applicable to tail command only) (-f is implicit. See the linux tail man page full list of options.) (Ex: --opts '-n 100')"
10
+ option ["-f", "--files files"], "File glob relative to app (default <application_name>/logs/*) (optional)"
11
+ option ["-g", "--gear ID"], "Tail only a specific gear"
12
+ #option ["-c", "--cartridge name"], "Tail only a specific cartridge"
13
+ alias_action :"app tail", :root_command => true, :deprecated => true
14
+ def run(app_name)
15
+ super app_name
16
+
17
+ 0
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,148 @@
1
+ require 'rhc/commands/base'
2
+
3
+ module RHC::Commands
4
+ class Member < Base
5
+ summary "Manage membership on domains"
6
+ syntax "<action>"
7
+ description <<-DESC
8
+ Teams of developers can collaborate on applications by adding people to
9
+ domains as members: each member has a role (admin, editor, or viewer),
10
+ and those roles determine what the user can do with the domain and the
11
+ applications contained within.
12
+
13
+ Roles:
14
+
15
+ view - able to see information about the domain and its apps, but not make any changes
16
+ edit - create, update, and delete applications, and has Git and SSH access
17
+ admin - can update membership of a domain
18
+
19
+ The default role granted to members when added is 'edit' - use the '--role'
20
+ argument to use another. When adding and removing members, you can use their
21
+ 'login' value (typically their email or a short unique name for them) or their
22
+ 'id'. Both login and ID are visible via the 'rhc account' command.
23
+
24
+ To see existing members of a domain or application, use:
25
+
26
+ rhc members -n <domain_name> [-a <app_name>]
27
+
28
+ To change the role for a user, simply call the add-member command with the new role. You
29
+ cannot change the role of the owner.
30
+ DESC
31
+ syntax "<action>"
32
+ default_action :help
33
+
34
+ summary "List members of a domain or application"
35
+ syntax "<domain_or_app_name> [-n DOMAIN_NAME] [-a APP_NAME]"
36
+ description <<-DESC
37
+ Show the existing members of a domain or application - you can pass the name
38
+ of your domain with '-n', the name of your application with '-a', or combine
39
+ them in the first argument to the command like:
40
+
41
+ rhc members <domain_name>/[<app_name>]
42
+
43
+ The owner is always listed first. To see the unique ID of members, pass
44
+ '--ids'.
45
+ DESC
46
+ option ['--ids'], "Display the IDs of each member", :optional => true
47
+ takes_application_or_domain :argument => true
48
+ alias_action :members, :root_command => true
49
+ def list(path)
50
+ target = find_app_or_domain(path)
51
+ members = target.members.sort_by{ |m| [m.owner? ? 0 : 1, m.role_weight, m.name] }
52
+ show_name = members.any?{ |m| m.name && m.name != m.login }
53
+ members.map! do |m|
54
+ [
55
+ ((m.name || "") if show_name),
56
+ m.login || "",
57
+ m.owner? ? "#{m.role} (owner)" : m.role,
58
+ (m.id if options.ids)
59
+ ].compact
60
+ end
61
+ say table(members, :header => [('Name' if show_name), 'Login', 'Role', ("ID" if options.ids)].compact)
62
+
63
+ 0
64
+ end
65
+
66
+ summary "Add or update a member on a domain"
67
+ syntax "<login> [<login>...] [-n DOMAIN_NAME] [--role view|edit|admin] [--ids]"
68
+ description <<-DESC
69
+ Adds or updates members on a domain by passing one or more login
70
+ or ids for other people on OpenShift. The login and ID values for each
71
+ account are displayed in 'rhc account'. To change the role for a user, simply
72
+ call the add-member command with the new role. You cannot change the role of
73
+ the owner.
74
+
75
+ Roles
76
+ view - able to see information about the domain and its apps,
77
+ but not make any changes
78
+ edit - create, update, and delete applications, and has Git
79
+ and SSH access
80
+ admin - can update membership of a domain
81
+
82
+ The default role granted to members when added is 'edit' - use the '--role'
83
+ argument for 'view' or 'admin'.
84
+
85
+ Examples
86
+ rhc add-member sally joe -n mydomain
87
+ Gives the accounts with logins 'sally' and 'joe' edit access on mydomain
88
+
89
+ rhc add-member bob@example.com --role admin -n mydomain
90
+ Gives the account with login 'bob@example.com' admin access on mydomain
91
+
92
+ DESC
93
+ takes_domain
94
+ option ['--ids'], "Treat the arguments as a list of IDs", :optional => true
95
+ option ['-r', '--role ROLE'], "The role to give to each member - view, edit, or admin (default 'edit')", :type => Role, :optional => true
96
+ argument :members, "A list of members logins to add. Pass --ids to treat this as a list of IDs.", [], :type => :list
97
+ def add(members)
98
+ target = find_domain
99
+ role = options.role || 'edit'
100
+ raise ArgumentError, 'You must pass one or more logins or ids to this command' unless members.present?
101
+ say "Adding #{pluralize(members.length, role_name(role))} to #{target.class.model_name.downcase} ... "
102
+ target.update_members(changes_for(members, role))
103
+ success "done"
104
+
105
+ 0
106
+ end
107
+
108
+ summary "Remove a member from a domain"
109
+ syntax "<login> [<login>...] [-n DOMAIN_NAME] [--ids]"
110
+ description <<-DESC
111
+ Remove members on a domain by passing one or more login or ids for each
112
+ member you wish to remove. View the list of existing members with
113
+ 'rhc members <domain_name>'.
114
+
115
+ Pass '--all' to remove all but the owner from the domain.
116
+ DESC
117
+ takes_domain
118
+ option ['--ids'], "Treat the arguments as a list of IDs"
119
+ option ['--all'], "Remove all members from this domain."
120
+ argument :members, "Member logins to remove from the domain. Pass --ids to treat this as a list of IDs.", [], :type => :list
121
+ def remove(members)
122
+ target = find_domain
123
+
124
+ if options.all
125
+ say "Removing all members from #{target.class.model_name.downcase} ... "
126
+ target.delete_members
127
+ success "done"
128
+
129
+ else
130
+ raise ArgumentError, 'You must pass one or more logins or ids to this command' unless members.present?
131
+ say "Removing #{pluralize(members.length, 'member')} from #{target.class.model_name.downcase} ... "
132
+ target.update_members(changes_for(members, 'none'))
133
+ success "done"
134
+ end
135
+
136
+ 0
137
+ end
138
+
139
+ protected
140
+ def changes_for(members, role)
141
+ members.map do |m|
142
+ h = {:role => role}
143
+ h[options.ids ? :id : :login] = m
144
+ h
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,197 @@
1
+ require 'uri'
2
+
3
+ module RHC::Commands
4
+ class ForwardingSpec
5
+ include RHC::Helpers
6
+ include Enumerable
7
+ # class to represent how SSH port forwarding should be performed
8
+ attr_accessor :port_from
9
+ attr_reader :remote_host, :port_to, :host_from, :service
10
+ attr_writer :bound
11
+
12
+ def initialize(service, remote_host, port_to, port_from = nil)
13
+ @service = service
14
+ @remote_host = remote_host
15
+ @port_to = port_to
16
+ @host_from = '127.0.0.1'
17
+ @port_from = port_from || port_to # match ports if possible
18
+ @bound = false
19
+ end
20
+
21
+ def to_cmd_arg
22
+ # string to be used in a direct SSH command
23
+ "-L #{port_from}:#{remote_host}:#{port_to}"
24
+ end
25
+
26
+ def to_fwd_args
27
+ # array of arguments to be passed to Net::SSH::Service::Forward#local
28
+ [port_from.to_i, remote_host, port_to.to_i]
29
+ end
30
+
31
+ def bound?
32
+ @bound
33
+ end
34
+
35
+ # :nocov: These are for sorting. No need to test for coverage.
36
+ def <=>(other)
37
+ if bound? && !other.bound?
38
+ -1
39
+ elsif !bound? && other.bound?
40
+ 1
41
+ else
42
+ order_by_attrs(other, :service, :remote_host, :port_from)
43
+ end
44
+ end
45
+
46
+ def order_by_attrs(other, *attrs)
47
+ # compare self and "other" by examining their "attrs" in order
48
+ # attrs should be an array of symbols to which self and "other"
49
+ # respond when sent.
50
+ while attribute = attrs.shift do
51
+ if self.send(attribute) != other.send(attribute)
52
+ return self.send(attribute) <=> other.send(attribute)
53
+ end
54
+ end
55
+ 0
56
+ end
57
+ # :nocov:
58
+
59
+ private :order_by_attrs
60
+ end
61
+
62
+ class PortForward < Base
63
+
64
+ UP_TO_256 = /25[0-5]|2[0-4][0-9]|[01]?(?:[0-9][0-9]?)/
65
+ UP_TO_65535 = /6553[0-5]|655[0-2][0-9]|65[0-4][0-9][0-9]|6[0-4][0-9][0-9][0-9]|[0-5]?(?:[0-9][0-9]{0,3})/
66
+ # 'host' part is a bit lax; we rely on 'rhc-list-ports' to hand us a reasonable output
67
+ # about the host information, be it numeric or FQDN in IPv4 or IPv6.
68
+ HOST_AND_PORT = /(.+):(#{UP_TO_65535})\b/
69
+
70
+ summary "Forward remote ports to the workstation"
71
+ syntax "<application>"
72
+ takes_application :argument => true
73
+ option ["-g", "--gear ID"], "Gear ID you are port forwarding to (optional)"
74
+ def run(app)
75
+ rest_app = find_app
76
+ ssh_uri = URI.parse(options.gear ? rest_app.gear_ssh_url(options.gear) : rest_app.ssh_url)
77
+
78
+ say "Using #{ssh_uri}..." if options.debug
79
+
80
+ forwarding_specs = []
81
+
82
+ begin
83
+ say "Checking available ports ... "
84
+
85
+ Net::SSH.start(ssh_uri.host, ssh_uri.user) do |ssh|
86
+ # If a specific gear is targeted, do not include remote (e.g. database) ports
87
+ list_ports_cmd = "rhc-list-ports#{options.gear ? ' --exclude-remote' : ''}"
88
+ ssh.exec! list_ports_cmd do |channel, stream, data|
89
+ if stream == :stderr
90
+ data.each_line do |line|
91
+ line.chomp!
92
+ # FIXME: This is really brittle; there must be a better way
93
+ # for the server to tell us that permission (what permission?)
94
+ # is denied.
95
+ raise RHC::PermissionDeniedException.new "Permission denied." if line =~ /permission denied/i
96
+ # ...and also which services are available for the application
97
+ # for us to forward ports for.
98
+ if line =~ /\A\s*(\S+) -> #{HOST_AND_PORT}\z/
99
+ debug fs = ForwardingSpec.new($1, $2, $3.to_i)
100
+ forwarding_specs << fs
101
+ else
102
+ debug line
103
+ end
104
+
105
+ end
106
+ end
107
+ end
108
+
109
+ if forwarding_specs.length == 0
110
+ # check if the gears have been stopped
111
+ if rest_app.gear_groups.all?{ |gg| gg.gears.all?{ |g| g["state"] == "stopped" } }
112
+ warn "none"
113
+ error "The application is stopped. Please restart the application and try again."
114
+ return 1
115
+ else
116
+ warn "none"
117
+ raise RHC::NoPortsToForwardException.new "There are no available ports to forward for this application. Your application may be stopped or idled."
118
+ end
119
+ end
120
+
121
+ success "done"
122
+
123
+ begin
124
+ Net::SSH.start(ssh_uri.host, ssh_uri.user) do |ssh|
125
+ say "Forwarding ports ..."
126
+ forwarding_specs.each do |fs|
127
+ given_up = nil
128
+ while !fs.bound? && !given_up
129
+ begin
130
+ args = fs.to_fwd_args
131
+ debug args.inspect
132
+ ssh.forward.local(*args)
133
+ fs.bound = true
134
+ rescue Errno::EADDRINUSE, Errno::EACCES => e
135
+ warn "#{e} while forwarding port #{fs.port_from}. Trying local port #{fs.port_from+1}"
136
+ fs.port_from += 1
137
+ rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e
138
+ given_up = true
139
+ end
140
+ end
141
+ end
142
+
143
+ bound_ports = forwarding_specs.select(&:bound?)
144
+ if bound_ports.length > 0
145
+ paragraph{ say "To connect to a service running on OpenShift, use the Local address" }
146
+ paragraph do
147
+ say table(
148
+ bound_ports.map do |fs|
149
+ [fs.service, "#{fs.host_from}:#{fs.port_from}", " => ", "#{fs.remote_host}:#{fs.port_to.to_s}"]
150
+ end,
151
+ :header => ["Service", "Local", " ", "OpenShift"]
152
+ )
153
+ end
154
+ end
155
+
156
+ # for failed port forwarding attempts
157
+ failed_port_forwards = forwarding_specs.select { |fs| !fs.bound? }
158
+ if failed_port_forwards.length > 0
159
+ ssh_cmd_arg = failed_port_forwards.map { |fs| fs.to_cmd_arg }.join(" ")
160
+ ssh_cmd = "ssh -N #{ssh_cmd_arg} #{ssh_uri.user}@#{ssh_uri.host}"
161
+ warn "Error forwarding some port(s). You can try to forward manually by running:\n#{ssh_cmd}"
162
+ else
163
+ say "Press CTRL-C to terminate port forwarding"
164
+ end
165
+
166
+ unless forwarding_specs.any?(&:bound?)
167
+ warn "No ports have been bound"
168
+ return
169
+ end
170
+ ssh.loop { true }
171
+ end
172
+ rescue Interrupt
173
+ say " Ending port forward"
174
+ return 0
175
+ end
176
+
177
+ end
178
+
179
+ rescue Timeout::Error, Errno::EADDRNOTAVAIL, Errno::EADDRINUSE, Errno::EHOSTUNREACH, Errno::ECONNREFUSED, Net::SSH::AuthenticationFailed => e
180
+ ssh_cmd = ["ssh","-N"]
181
+ unbound_fs = forwarding_specs.select { |fs| !fs.bound? }
182
+ ssh_cmd += unbound_fs.map { |fs| fs.to_cmd_arg }
183
+ ssh_cmd += ["#{ssh_uri.user}@#{ssh_uri.host}"]
184
+ raise RHC::PortForwardFailedException.new("#{e.message + "\n" if options.debug}Error trying to forward ports. You can try to forward manually by running:\n" + ssh_cmd.join(" "))
185
+ end
186
+
187
+ 0
188
+ rescue RHC::Rest::ConnectionException => e
189
+ error "Connection to #{openshift_server} failed: #{e.message}"
190
+ 1
191
+ end
192
+ end
193
+ end
194
+
195
+ # mock for windows
196
+ if defined?(UNIXServer) != 'constant' or UNIXServer.class != Class then class UNIXServer; end; end
197
+
@@ -0,0 +1,17 @@
1
+ require 'rhc/commands/app'
2
+
3
+ module RHC::Commands
4
+ class Reload < App
5
+
6
+ summary "Reload the application's configuration"
7
+ syntax "<app> [--namespace NAME]"
8
+ takes_application :argument => true
9
+
10
+ def run(app)
11
+ self.class.superclass.instance_method(:reload).bind(self).call app
12
+
13
+ 0
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ require 'rhc/commands/app'
2
+
3
+ module RHC::Commands
4
+ class Restart < App
5
+
6
+ summary "Restart the application"
7
+ syntax "<app> [--namespace NAME]"
8
+ takes_application :argument => true
9
+
10
+ def run(app)
11
+ self.class.superclass.instance_method(:restart).bind(self).call app
12
+
13
+ 0
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,54 @@
1
+ require 'rhc/commands/base'
2
+ require 'rhc/scp_helpers'
3
+
4
+
5
+ module RHC::Commands
6
+ class Scp < Base
7
+ suppress_wizard
8
+
9
+ summary "SCP a file to or from your application"
10
+ description <<-DESC
11
+ Transfer files to and from your applications using SCP. This will transfer
12
+ files to and from your primary gear (the one with the Git repository and web
13
+ cartridge) by default.
14
+
15
+ Examples:
16
+ Uploading a file from your workding directory to your app-root/data directory
17
+ app scp myapp upload somefile.txt app-root/data
18
+
19
+ Downloading a file from your app-root/data directory to your working directory
20
+ app scp myapp download ./ app-root/data/somebigarchive.tar.gz
21
+ DESC
22
+ syntax "[<app> --] <action> <local_path> <remote_path>"
23
+ takes_application :argument => true
24
+ argument :action, "Transfer direction: upload|download", ["-t", "--transfer_direction upload|download"], :optional => false
25
+ argument :local_path, "Local filesystem path", ["-l", "--local_path file_path"], :optional => false
26
+ argument :remote_path, "Remote filesystem path", ["-r", "--remote_path file_path"], :optional => false
27
+ alias_action 'app scp', :root_command => true
28
+ def run(_, action, local_path, remote_path)
29
+ rest_app = find_app
30
+ ssh_opts = rest_app.ssh_url.gsub("ssh://","").split("@")
31
+
32
+ raise RHC::ArgumentNotValid.new("'#{action}' is not a valid argument for this command. Please use upload or download.") unless action == 'download' || action == 'upload'
33
+ raise RHC::FileOrPathNotFound.new("Local file, file_path, or directory could not be found.") unless File.exist?(local_path)
34
+
35
+ begin
36
+ start_time = Time.now
37
+ Net::SCP.send("#{action}!".to_sym, ssh_opts[1], ssh_opts[0], (action == 'upload' ? local_path : remote_path), (action == 'upload' ? remote_path : local_path)) do |ch, name, sent, total|
38
+ #:nocov:
39
+ $stderr.print "\r #{action}ing #{name}: #{((sent.to_f/total.to_f)*100).to_i}% complete. #{sent}/#{total} bytes transferred " + (sent == total ? "in #{Time.now - start_time} seconds \n" : "")
40
+ #:nocov:
41
+ end
42
+ rescue Errno::ECONNREFUSED
43
+ raise RHC::SSHConnectionRefused.new(ssh_opts[0], ssh_opts[1])
44
+ rescue SocketError => e
45
+ raise RHC::ConnectionFailed, "The connection to #{ssh_opts[1]} failed: #{e.message}"
46
+ rescue Net::SCP::Error => e
47
+ raise RHC::RemoteFileOrPathNotFound.new("Remote file, file_path, or directory could not be found.")
48
+ end
49
+ end
50
+
51
+ protected
52
+ include RHC::SCPHelpers
53
+ end
54
+ end
@@ -0,0 +1,40 @@
1
+ module RHC::Commands
2
+ class Server < Base
3
+ suppress_wizard
4
+
5
+ summary "Display information about the status of the OpenShift service"
6
+ description <<-DESC
7
+ Retrieves any open issues or notices about the operation of the
8
+ OpenShift service and displays them in the order they were opened.
9
+
10
+ When connected to an OpenShift Enterprise server, will only display
11
+ the version of the API that it is connecting to.
12
+ DESC
13
+ def run
14
+ say "Connected to #{openshift_server}"
15
+
16
+ if openshift_online_server?
17
+ #status = decode_json(get("#{openshift_url}/app/status/status.json").body)
18
+ status = rest_client.request(:method => :get, :url => "#{openshift_url}/app/status/status.json", :lazy_auth => true){ |res| decode_json(res.content) }
19
+ open = status['open']
20
+
21
+ (success 'All systems running fine' and return 0) if open.blank?
22
+
23
+ open.each do |i|
24
+ i = i['issue']
25
+ say color("%-3s %s" % ["##{i['id']}", i['title']], :bold)
26
+ items = i['updates'].map{ |u| [u['description'], date(u['created_at'])] }
27
+ items.unshift ['Opened', date(i['created_at'])]
28
+ table(items, :align => [nil,:right], :join => ' ').each{ |s| say " #{s}" }
29
+ end
30
+ say "\n"
31
+ warn pluralize(open.length, "open issue")
32
+
33
+ open.length #exit with the count of open items
34
+ else
35
+ success "Using API version #{rest_client.api_version_negotiated}"
36
+ 0
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,60 @@
1
+ require 'rhc/commands/base'
2
+ require 'rhc/wizard'
3
+ require 'rhc/config'
4
+
5
+ module RHC::Commands
6
+ class Setup < Base
7
+ suppress_wizard
8
+
9
+ summary "Connects to StartApp and sets up your keys and domain"
10
+ description <<-DESC
11
+ Connects to an StartApp server to get you started. Will help you
12
+ configure your SSH keys, set up a domain, and check for any potential
13
+ problems with Git or SSH.
14
+
15
+ Any options you pass to the setup command will be stored in a
16
+ .openshift/express.conf file in your home directory. If you run
17
+ setup at a later time, any previous configuration will be reused.
18
+
19
+ Pass the --clean option to ignore your saved configuration and only
20
+ use options you pass on the command line. Pass --config FILE to use
21
+ default values from another config (the values will still be written
22
+ to .startapp/express.conf).
23
+
24
+ If the server supports authorization tokens, you may pass the
25
+ --create-token option to instruct the wizard to generate a key for you.
26
+
27
+ If you would like to enable tab-completion in Bash shells, pass
28
+ --autocomplete for more information.
29
+ DESC
30
+ option ["--server NAME"], "Hostname of an OpenShift server", :default => :server_context, :required => true
31
+ option ['--clean'], "Ignore any saved configuration options"
32
+ option ['--[no-]create-token'], "Create an authorization token for this server"
33
+ option ['--autocomplete'], "Instructions for enabling tab-completion"
34
+ def run
35
+ if options.autocomplete
36
+ src = File.join(File.join(Gem.loaded_specs['app'].full_gem_path, "autocomplete"), "rhc_bash")
37
+ dest = File.join(RHC::Config.home_conf_dir, "bash_autocomplete")
38
+
39
+ FileUtils.mkdir_p(RHC::Config.home_conf_dir)
40
+ FileUtils.cp(src, dest)
41
+
42
+ say <<-LINE.strip_heredoc
43
+ To enable tab-completion for `app` under Bash shells, add the following command to
44
+ your .bashrc or .bash_profile file:
45
+
46
+ . #{dest}
47
+
48
+ Save your shell and then restart. Type "app" and then hit the TAB key twice to
49
+ trigger completion of your command.
50
+
51
+ Tab-completion is not available in the Windows terminal.
52
+ LINE
53
+ return 0
54
+ end
55
+
56
+ raise OptionParser::InvalidOption, "Setup can not be run with the --noprompt option" if options.noprompt
57
+ RHC::RerunWizard.new(config, options).run ? 0 : 1
58
+ end
59
+ end
60
+ end