c66 0.1.0

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.
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: []