c66 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Cloud66 Limited.
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # Cloud 66 Toolbelt: c66
2
+
3
+ Cloud 66 Toolbelt is a simple command-line tool for the awesome Cloud 66 customers. It allows you to deploy, modify settings and retrieve the current status of your Cloud 66 stacks, and much more!
4
+
5
+ ## Installation
6
+
7
+ You can install the Cloud 66 Toolbelt using [RubyGems](http://rubygems.org/):
8
+
9
+ $ gem install c66
10
+
11
+ ## Usage
12
+
13
+ ### Help
14
+ With c66 installed, you can display the help with one of the following instructions:
15
+
16
+ $ c66 help
17
+
18
+ or
19
+
20
+ $ c66
21
+
22
+ ### Initialize the Toolbelt
23
+
24
+ Firstly, to use the Toolbelt, you will need to initiate it using:
25
+
26
+ $ c66 init
27
+
28
+ Then visit the URL given once authorized, copy and paste the `authorization code` into the command-line interface.
29
+
30
+ You need to sign in and allow the Cloud 66 Toolbelt application to use your account to access to the authorization code.
31
+
32
+ Note: This is a one-off task.
33
+
34
+ ### List the Stacks
35
+
36
+ You can list all your stacks using:
37
+
38
+ $ c66 list
39
+
40
+ ### Deploy a Stack
41
+
42
+ Deploy a stack using the command `deploy` with a stack UID (Unique Identifer):
43
+
44
+ $ c66 deploy --stack <stack_UID>
45
+
46
+ or
47
+
48
+ $ c66 deploy -s <stack_UID>
49
+
50
+ You can retrieve the UID of a stack using the `list` command.
51
+
52
+ Through the Cloud 66 interface, click on your stack, then click on the cog and select the stack information view to retrieve the UID:
53
+
54
+ ![stack_uid](http://cdn.cloud66.com.s3.amazonaws.com/images/Toolbelt/exemple_stack_uid.PNG)
55
+
56
+ The stack UID is saved when you deploy through the Cloud 66 Toolbelt. It allows you to deploy a stack without putting the stack UID every time:
57
+
58
+ $ c66 deploy
59
+
60
+ you can use a short-cut for this command:
61
+
62
+ $ c66 d
63
+
64
+ ### Settings of a Stack
65
+
66
+ It is possible to retrieve the settings of a specified stack and to easily modify them:
67
+
68
+ To display the settings:
69
+
70
+ $ c66 settings --stack <stack_UID>
71
+
72
+ or
73
+
74
+ $ c66 settings -s <stack_UID>
75
+
76
+ If your stack UID is saved:
77
+
78
+ $ c66 settings
79
+
80
+ To modify a setting:
81
+
82
+ $ c66 set --stack <stack_UID> --setting_name <setting_name> --value <value>
83
+
84
+ or
85
+
86
+ $ c66 set -s <stack_UID> -n <setting_name> -v <value>
87
+
88
+ If the stack UID is saved:
89
+
90
+ $ c66 set --setting_name <setting_name> --value <value>
91
+
92
+ or
93
+
94
+ $ c66 set -n <setting_name> -v <value>
95
+
96
+
97
+ ## Contributing
98
+
99
+ 1. Fork it
100
+
101
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
102
+
103
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
104
+
105
+ 4. Push to the branch (`git push origin my-new-feature`)
106
+
107
+ 5. Create new Pull Request
108
+
109
+ ## Copyright
110
+
111
+ Copyright (c) 2013 Cloud66 Limited.. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/c66.rb ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "c66"
4
+
5
+ C66.thorStart
data/c66.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'c66/utils/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "c66"
8
+ spec.version = C66::Utils::VERSION
9
+ spec.authors = ["Cloud 66"]
10
+ spec.email = ["hello@cloud66.com"]
11
+ spec.description = "See https://www.cloud66.com for more info"
12
+ spec.summary = "Cloud 66 Toolbelt"
13
+ spec.homepage = "https://www.cloud66.com"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "bundler", "~> 1.3"
22
+ spec.add_dependency "rake", "~> 10.1.0"
23
+ spec.add_dependency "thor", "~> 0.18.1"
24
+ spec.add_dependency "oauth2", "~> 0.9.2"
25
+ spec.add_dependency "json", "~> 1.7.7"
26
+ spec.add_dependency "httparty", "~> 0.11.0"
27
+ end
@@ -0,0 +1,288 @@
1
+ require "rubygems"
2
+ require "thor"
3
+ require "oauth2"
4
+ require "json"
5
+ require "httparty"
6
+
7
+ module C66
8
+ module Commands
9
+
10
+ CLIENT_NAME = 'c66'
11
+
12
+ STK_QUEUED = 0
13
+ STK_SUCCESS = 1
14
+ STK_FAILED = 2
15
+ STK_ANALYSING = 3
16
+ STK_ANALYSED = 4
17
+ STK_QUEUED_FOR_DEPLOYING = 5
18
+ STK_DEPLOYING = 6
19
+ STK_TERMINAL_FAILURE = 7
20
+
21
+ STATUS = {
22
+ STK_QUEUED => 'Pending analysis',
23
+ STK_SUCCESS => 'Deployed successfully',
24
+ STK_FAILED => 'Deployment failed',
25
+ STK_ANALYSING => 'Analyzing',
26
+ STK_ANALYSED => 'Analyzed',
27
+ STK_QUEUED_FOR_DEPLOYING => 'Queued for deployment',
28
+ STK_DEPLOYING => 'Deploying',
29
+ STK_TERMINAL_FAILURE => 'Unable to analyze'
30
+ }
31
+
32
+ VERSION_FILE = 'http://cdn.cloud66.com/config/cloud66_toolbelt.json'
33
+ BASE_URL = 'https://www.cloud66.com'
34
+
35
+ class C66Toolbelt < Thor
36
+ no_commands {
37
+ def values
38
+ @values ||=
39
+ { :base_url => "#{BASE_URL}/api/2",
40
+ :client_id => "638412995ee3da6f67e24564ac297f9554ee253a8fe1502348c4d6e845bd9d0d",
41
+ :client_secret => "961398353aa6e7f0f36dfcd83e447d748c54481b7a3b143e0119441516e8b91f",
42
+ :scope => "public redeploy",
43
+ :redirect_url => "urn:ietf:wg:oauth:2.0:oob",
44
+ :auth_url => "#{BASE_URL}/oauth/authorize",
45
+ :token_url => "#{BASE_URL}/oauth/token"
46
+ }
47
+ end
48
+
49
+ def base_url
50
+ values[:base_url]
51
+ end
52
+
53
+ def c66_path
54
+ File.join(File.expand_path("~"), ".cloud66")
55
+ end
56
+
57
+ def stack_path
58
+ File.join(File.expand_path("."), ".cloud66")
59
+ end
60
+
61
+ def config
62
+ if @config.nil?
63
+ load_config
64
+ end
65
+
66
+ @config
67
+ end
68
+
69
+ def config_file
70
+ File.join(c66_path, "toolbelt.json")
71
+ end
72
+
73
+ def params_file
74
+ File.join(c66_path, "params.json")
75
+ end
76
+
77
+ def stack_file
78
+ File.join(stack_path, "stack.json")
79
+ end
80
+
81
+ def load_config
82
+ if File.exists?(config_file)
83
+ @config = JSON.load(IO.read(config_file))
84
+ else
85
+ abort("No config file found at #{config_file}. Run #{CLIENT_NAME} init to register your client")
86
+ end
87
+ end
88
+
89
+ def save_config
90
+ if !File.directory?(c66_path)
91
+ Dir.mkdir_p(c66_path)
92
+ end
93
+
94
+ File.open(config_file,"w") do |f|
95
+ f.write(@config.to_json)
96
+ end
97
+ end
98
+
99
+ def save_stack(stack_id)
100
+ if !File.directory?(stack_path)
101
+ Dir.mkdir(stack_path)
102
+ end
103
+ @stack_json = { :stack_id => stack_id}
104
+ File.open(stack_file,"w") do |f|
105
+ f.write(@stack_json.to_json)
106
+ end
107
+ @stack = stack_id
108
+ say "Stack #{stack_id} saved to #{stack_file}"
109
+ end
110
+
111
+ def load_stack
112
+ if File.exists?(stack_file)
113
+ if @stack = JSON.load(IO.read(stack_file))['stack_id']
114
+ say "Stack #{@stack} loaded."
115
+ else
116
+ abort "No stack id found at #{stack_file}"
117
+ end
118
+ else
119
+ say("No stack saved at #{stack_file}.")
120
+ end
121
+ end
122
+
123
+ def load_params
124
+ if File.exists?(params_file) && File.size(params_file)!=0
125
+ begin
126
+ @params= JSON.load(IO.read(params_file))
127
+ rescue => e
128
+ abort "#{params_file} is not a valid JSON file"
129
+ end
130
+ if @params.has_key? 'base_url'
131
+ values[:base_url] = @params['base_url']
132
+ else
133
+ abort "Missing 'base_url' parameter in #{params_file}"
134
+ end
135
+ if @params.has_key? 'client_id'
136
+ values[:client_id] = @params['client_id']
137
+ else
138
+ abort "Missing 'client_id' parameter in #{params_file}"
139
+ end
140
+ if @params.has_key? 'client_secret'
141
+ values[:client_secret] = @params['client_secret']
142
+ else
143
+ abort "Missing 'client_secret' parameter in #{params_file}"
144
+ end
145
+ say "Parameters loaded."
146
+ end
147
+ end
148
+
149
+ def get_stack(stack)
150
+ save_stack(stack) if stack
151
+ load_stack if stack.nil?
152
+ end
153
+
154
+ def client
155
+ @client ||= OAuth2::Client.new(values[:client_id], values[:client_secret], :site => values[:base_url])
156
+ end
157
+
158
+ def token
159
+ load_config
160
+
161
+ if @config.has_key? 'token'
162
+ OAuth2::AccessToken.new(client, @config['token'])
163
+ else
164
+ abort "No authentication token found. run #{CLIENT_NAME} init to register your client"
165
+ end
166
+ end
167
+
168
+ def parse_response(response)
169
+ begin
170
+ JSON.parse(response.body)
171
+ rescue => e
172
+ abort e.message
173
+ end
174
+ end
175
+
176
+ def self.get_version
177
+ begin
178
+ JSON.load(HTTParty.get(VERSION_FILE)).fetch("version")
179
+ rescue => e
180
+ puts "Failed to retrieve the latest version of Cloud 66 Toolbelt, please contact us"
181
+ end
182
+ end
183
+
184
+
185
+ def self.compare_versions
186
+ result = C66::Utils::VERSION<=>get_version
187
+ case result
188
+ when 0..1
189
+ #say "Version is up-to-date."
190
+ when -1
191
+ puts "There is a new version of Cloud66 Toolbelt. Pease run \"gem update #{CLIENT_NAME}\"."
192
+ end
193
+ end
194
+ }
195
+
196
+ package_name "Cloud 66 Toolbelt"
197
+ desc "init", "Initialize the toolbelt"
198
+ map "d" => :deploy
199
+
200
+ compare_versions
201
+
202
+
203
+ long_desc <<-LONGDESC
204
+ Initialize Cloud 66 toolbelt
205
+ LONGDESC
206
+ def init
207
+ load_params
208
+ result = client.auth_code.authorize_url(:redirect_uri => values[:redirect_url], :scope => values[:scope])
209
+
210
+ say "Visit the URL below and paste the initialization code here"
211
+ say result
212
+
213
+ auth_code = ask("Authorization Code:")
214
+
215
+ begin
216
+ token = client.auth_code.get_token(auth_code, :redirect_uri => values[:redirect_url])
217
+ rescue OAuth2::Error => e
218
+ abort e.message
219
+ end
220
+
221
+ @config = { :auth_code => auth_code, :token => token.token, :refresh_token => token.refresh_token }
222
+ save_config
223
+
224
+ say "Configuration saved to #{config_file}"
225
+ end
226
+
227
+ desc "list", "Lists all the stacks"
228
+ def list
229
+ response = parse_response(token.get("#{base_url}/stacks.json"))
230
+
231
+ if response['count'] != 0
232
+ response['response'].each do |stack|
233
+ say "#{stack['name']} (#{stack['uid']}) : #{stack['environment']} - #{STATUS[stack['status']]}"
234
+ end
235
+ else
236
+ say "No stacks found"
237
+ end
238
+ end
239
+
240
+ desc "settings", "Get the list of settings for this stack"
241
+ option :stack, :aliases => "-s", :required => false
242
+ def settings()
243
+ begin
244
+ get_stack(options[:stack])
245
+ abort "No stack provided or saved, please use '--stack' or '-s' option" if @stack.nil?
246
+ response = token.get("#{base_url}/stacks/#{@stack}/settings.json")
247
+ settings = JSON.parse(response.body)['response']
248
+
249
+ abort "No settings found" if settings.nil?
250
+
251
+ settings.each do |setting|
252
+ say "#{setting['key']}\t\t#{setting['value']}\t#{setting['readonly'] ? '(readonly)' : ''}\r\n"
253
+ end
254
+ rescue OAuth2::Error => e
255
+ abort e.message
256
+ end
257
+ end
258
+
259
+ desc "set", "Set the value of a specific setting"
260
+ option :stack, :aliases => "-s", :required => false
261
+ option :setting_name, :aliases => "-n", :required => true
262
+ option :value, :aliases => "-v", :required => true
263
+ def set()
264
+ begin
265
+ get_stack(options[:stack])
266
+ abort "No stack provided or saved, please use '--stack' or '-s' option" if @stack.nil?
267
+ response = token.post("#{base_url}/stacks/#{@stack}/setting.json", { :body => { :setting_name => options[:setting_name], :setting_value => options[:value] }})
268
+ say "Setting applied" if JSON.parse(response.body)['response']['ok']
269
+ rescue OAuth2::Error => e
270
+ abort e.message
271
+ end
272
+ end
273
+
274
+ desc "deploy", "Deploy the given stack"
275
+ option :stack, :aliases => "-s", :required => false
276
+ def deploy()
277
+ begin
278
+ get_stack(options[:stack])
279
+ abort "No stack provided or saved, please use '--stack' or '-s' option" if @stack.nil?
280
+ response = token.post("#{base_url}/stacks/#{@stack}/redeploy.json", {})
281
+ say JSON.parse(response.body)['response']['message']
282
+ rescue OAuth2::Error => e
283
+ abort "Could't find your stack, maybe it was moved, deleted or you accidentally mistyped the stack ID"
284
+ end
285
+ end
286
+ end
287
+ end
288
+ end
@@ -0,0 +1,6 @@
1
+ module C66
2
+ module Utils
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
6
+
data/lib/c66.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "c66/utils/version"
2
+ require "c66/commands/c66_toolbelt"
3
+
4
+ module C66
5
+ def self.thorStart
6
+ Commands::C66Toolbelt.start
7
+ end
8
+ end
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: c66
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Cloud 66
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: &70093107966800 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '1.3'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70093107966800
25
+ - !ruby/object:Gem::Dependency
26
+ name: rake
27
+ requirement: &70093107966180 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 10.1.0
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70093107966180
36
+ - !ruby/object:Gem::Dependency
37
+ name: thor
38
+ requirement: &70093107965480 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 0.18.1
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70093107965480
47
+ - !ruby/object:Gem::Dependency
48
+ name: oauth2
49
+ requirement: &70093107964520 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.9.2
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70093107964520
58
+ - !ruby/object:Gem::Dependency
59
+ name: json
60
+ requirement: &70093107963280 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ~>
64
+ - !ruby/object:Gem::Version
65
+ version: 1.7.7
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *70093107963280
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: &70093107962820 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ~>
75
+ - !ruby/object:Gem::Version
76
+ version: 0.11.0
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: *70093107962820
80
+ description: See https://www.cloud66.com for more info
81
+ email:
82
+ - hello@cloud66.com
83
+ executables:
84
+ - c66.rb
85
+ extensions: []
86
+ extra_rdoc_files: []
87
+ files:
88
+ - .gitignore
89
+ - Gemfile
90
+ - LICENSE.txt
91
+ - README.md
92
+ - Rakefile
93
+ - bin/c66.rb
94
+ - c66.gemspec
95
+ - lib/c66.rb
96
+ - lib/c66/commands/c66_toolbelt.rb
97
+ - lib/c66/utils/version.rb
98
+ homepage: https://www.cloud66.com
99
+ licenses:
100
+ - MIT
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project:
119
+ rubygems_version: 1.8.15
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: Cloud 66 Toolbelt
123
+ test_files: []