qtc-sdk 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ae1a61e36df4c88b7796881f0c73fd5472094bd4
4
+ data.tar.gz: 6fab0aab05f54655cc57c06dd4e74eff2abe3f18
5
+ SHA512:
6
+ metadata.gz: 9ef6371c511a18cae763e32c577e8f5a62424a8ff78bafe8457d0dac9ef94cdfb17c47badea6dbb4a129c5318e4571bba7a929f4311bdeb7f7b599c5c17b2dfc
7
+ data.tar.gz: d91e9aba94dcf0a24244436671cbae52533f43c463b2b49089dad2e25639451c8e7b77b28a15a9bf2ca7a46eca71005c467e030d0fc79e78efee88dbded1e149
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .idea
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in qtc-sdk.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Jari Kolehmainen
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,44 @@
1
+ # Qt Cloud Services SDK for Ruby
2
+
3
+ This is Qt Cloud Services SDK for Ruby. What is Qt Cloud Services? See below:
4
+
5
+ * The Qt Cloud Services home page is at https://www.qtc.io
6
+ * The Developer Documentation page is at https://developer.qtc.io
7
+
8
+ ## Getting Started
9
+
10
+ You can find a getting started guide for Qt Cloud Services at:
11
+
12
+ http://developer.qtc.io/qtc/getting-started?snippets=ruby
13
+
14
+ If you are looking for service specific guides, please see:
15
+
16
+ * [Enginio Data Storage](http://developer.qtc.io/eds/getting-started?snippets=ruby)
17
+ * [Managed Application Runtime](http://developer.qtc.io/mar/getting-started?snippets=ruby)
18
+
19
+
20
+ ## Installation
21
+
22
+ Add this line to your application's Gemfile:
23
+
24
+ gem 'qtc-sdk'
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install qtc-sdk
33
+
34
+ ## Usage
35
+
36
+ TODO: Write usage instructions here
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it ( http://github.com/jakolehm/qtc-sdk-ruby/fork )
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/qtc-cli ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+
4
+ # resolve bin path, ignoring symlinks
5
+ require 'pathname'
6
+ bin_file = Pathname.new(__FILE__).realpath
7
+
8
+ # add self to libpath
9
+ $:.unshift File.expand_path('../../lib', bin_file)
10
+
11
+ STDOUT.sync = true
12
+
13
+ require 'commander/import'
14
+ require 'qtc/cli/commands'
@@ -0,0 +1,34 @@
1
+ require 'qtc/client'
2
+ require_relative 'common'
3
+
4
+ module Qtc
5
+ module Cli
6
+ class Clouds
7
+ include Common
8
+
9
+ def list
10
+ accounts = platform_client.get('/user/accounts')
11
+ accounts['results'].each do |account|
12
+ print color("~ #{account['name']} (#{account['id']})", :bold)
13
+ end
14
+ end
15
+
16
+ def login
17
+ pass = password("Personal Access Token (copy from https://console.qtcloudservices.com/#/user/profile):")
18
+ inifile['platform']['token'] = pass
19
+
20
+ response = platform_client(pass).get('/user/accounts', {}) rescue nil
21
+ if response
22
+ inifile.save(filename: ini_filename)
23
+ else
24
+ print color('Invalid Personal Access Token', :red)
25
+ end
26
+ end
27
+
28
+ def logout
29
+ inifile['platform'].delete('token')
30
+ inifile.save(filename: ini_filename)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ require 'qtc/version'
2
+
3
+ program :name, 'qtc-cli'
4
+ program :version, Qtc::VERSION
5
+ program :description, 'Command line interface for Qt Cloud Services'
6
+
7
+ default_command :help
8
+ never_trace!
9
+
10
+ require_relative 'clouds'
11
+ command 'clouds' do |c|
12
+ c.syntax = 'qtc-cli clouds'
13
+ c.description = 'List all clouds'
14
+ c.action do |args, options|
15
+ Qtc::Cli::Clouds.new.list
16
+ end
17
+ end
18
+
19
+ command 'login' do |c|
20
+ c.syntax = 'qtc-cli login'
21
+ c.description = 'Login to Qt Cloud Services'
22
+ c.action do |args, options|
23
+ Qtc::Cli::Clouds.new.login
24
+ end
25
+ end
26
+
27
+ command 'logout' do |c|
28
+ c.syntax = 'qtc-cli logout'
29
+ c.description = 'Logout from Qt Cloud Services'
30
+ c.action do |args, options|
31
+ Qtc::Cli::Clouds.new.logout
32
+ end
33
+ end
34
+
35
+ require_relative 'eds/commands'
36
+ require_relative 'mar/commands'
@@ -0,0 +1,93 @@
1
+ require 'inifile'
2
+ module Qtc
3
+ module Cli
4
+ module Common
5
+
6
+ def instance_info(instance_id)
7
+ instance_data = platform_client.get("/instances/#{instance_id}")
8
+ if instance_data
9
+ response = platform_client.get("/instances/#{instance_id}/authorizations")
10
+ if response['results']
11
+ instance_data['authorizations'] = response['results']
12
+ end
13
+ else
14
+ abort("Error: instance not found")
15
+ end
16
+
17
+ instance_data
18
+ end
19
+
20
+ def platform_client(token = nil)
21
+ inifile['platform']['token'] = token unless token.nil?
22
+ unless inifile['platform']['token']
23
+ raise ArgumentError.new("Please login first using: qtc-cli login")
24
+ end
25
+
26
+ if @platform_client.nil?
27
+ @platform_client = Qtc::Client.new(platform_base_url, {'Authorization' => "Bearer #{inifile['platform']['token']}"})
28
+ end
29
+
30
+ @platform_client
31
+ end
32
+
33
+ def ini_filename
34
+ File.join(Dir.home, '/.qtc_client')
35
+ end
36
+
37
+ def inifile
38
+ if @inifile.nil?
39
+ if File.exists?(ini_filename)
40
+ @inifile = IniFile.load(ini_filename)
41
+ else
42
+ @inifile = IniFile.new
43
+ end
44
+ end
45
+
46
+ unless @inifile['platform']
47
+ @inifile['platform'] = {}
48
+ end
49
+
50
+ @inifile
51
+ end
52
+
53
+ ##
54
+ # @param [String,NilClass]
55
+ # @return [String]
56
+ def extract_app_in_dir(remote = nil)
57
+ if File.exists?(File.expand_path('./.git/config'))
58
+ remotes = []
59
+ git_remotes = `git remote -v`
60
+ git_remotes.lines.each do |line|
61
+ if match = line.match(/#{remote}\s+git@git-mar-(.*)\:(.*) \(push\)/)
62
+ remotes << match[2]
63
+ end
64
+ end
65
+ apps = remotes.uniq
66
+ if apps.size == 1
67
+ return apps[0]
68
+ elsif apps.size > 1
69
+ raise ArgumentError.new("Multiple app git remotes\nSpecify app with --remote REMOTE or --app APP")
70
+ end
71
+ end
72
+ end
73
+
74
+ ##
75
+ # @return [Qtc::Client]
76
+ def client
77
+ if @client.nil?
78
+ @client = Qtc::Client.new(base_url)
79
+ end
80
+
81
+ @client
82
+ end
83
+
84
+ def base_url
85
+ ENV['QTC_MAR_URL'] || 'https://mar-eu-1.qtc.io/v1'
86
+ end
87
+
88
+ def platform_base_url
89
+ ENV['QTC_PLATFORM_URL'] || 'https://api.qtc.io/v1'
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,28 @@
1
+ require 'qtc/client'
2
+ require_relative '../common'
3
+
4
+ module Qtc
5
+ module Cli
6
+ module Eds
7
+ class Base
8
+ include Cli::Common
9
+
10
+ protected
11
+
12
+ ##
13
+ # @return [Qtc::Client]
14
+ def client
15
+ if @client.nil?
16
+ @client = Qtc::Client.new(base_url)
17
+ end
18
+
19
+ @client
20
+ end
21
+
22
+ def base_url
23
+ ENV['QTC_EDS_URL'] || 'https://api.engin.io/v1'
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,20 @@
1
+ require_relative 'instances'
2
+
3
+ command 'eds list' do |c|
4
+ c.syntax = 'qtc-cli eds list'
5
+ c.description = 'List all EDS instances'
6
+ c.action do |args, options|
7
+ Qtc::Cli::Eds::Instances.new.list
8
+ end
9
+ end
10
+
11
+ command 'eds create' do |c|
12
+ c.syntax = 'qtc-cli eds create <CLOUD_ID> <NAME>'
13
+ c.description = 'Create a new EDS instance'
14
+ c.example 'Create new EDS instance "My Backend" to cloud "46738209-a745-4841-8eeb-1ca0672aa6v8"', 'qtc-cli eds create 46738209-a745-4841-8eeb-1ca0672aa6v8 "My Backend"'
15
+ c.action do |args, options|
16
+ raise ArgumentError.new('CLOUD_ID is required') if args[0].nil?
17
+ raise ArgumentError.new('NAME is required') if args[1].nil?
18
+ Qtc::Cli::Eds::Instances.new.create(args[0], args[1])
19
+ end
20
+ end
@@ -0,0 +1,30 @@
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Eds::Instances < Eds::Base
6
+
7
+ def list
8
+ accounts = platform_client.get('/user/accounts')
9
+ accounts['results'].each do |account|
10
+ print color("== #{account['name']}: #{account['id']}", :cyan)
11
+ instances = platform_client.get("/accounts/#{account['id']}/instances", {provider: 'eds'})
12
+ instances['results'].each do |instance|
13
+ say(" ~ <%= color('#{instance['id']}', :green) %> #{instance['name']} <%= color('#{instance['tags'].join(', ')}', :yellow) %>")
14
+ end
15
+ puts ''
16
+ end
17
+ end
18
+
19
+ def create(cloud_id, name)
20
+ data = {
21
+ name: name,
22
+ serviceProviderId: 'eds',
23
+ datacenterId: options.datacenter || 'eu-1'
24
+ }
25
+ response = platform_client.post("/accounts/#{cloud_id}/instances", data)
26
+ puts response['id']
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,105 @@
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Mar::Apps < Mar::Base
6
+
7
+ def list
8
+ accounts = platform_client.get('/user/accounts')
9
+ accounts['results'].each do |account|
10
+ print color("== #{account['name']}: #{account['id']}")
11
+ instances = platform_client.get("/accounts/#{account['id']}/instances", {provider: 'mar'})
12
+ instances['results'].each do |instance|
13
+ if instance['config']['MAR_GIT_ADDRESS']
14
+ say(" ~ <%= color('#{instance['id']}', :green) %> #{instance['name']} <%= color('#{instance['tags'].join(', ')}', :yellow) %>")
15
+ end
16
+ end
17
+ puts ''
18
+ end
19
+ end
20
+
21
+ def show(options)
22
+ instance_id = resolve_instance_id(options)
23
+
24
+ instance_data = instance_info(instance_id)
25
+ if instance_data
26
+ token = instance_data['authorizations'][0]['access_token']
27
+ result = client.get("/apps/#{instance_id}", nil, {'Authorization' => "Bearer #{token}"})
28
+ say "Id: #{result['id']}"
29
+ puts "Name: #{result['name']}"
30
+ puts "Size: #{result['size']}"
31
+ puts "State: #{result['state']}"
32
+ puts "Structure: #{JSON.pretty_generate(result['structure'])}"
33
+ status = client.get("/apps/#{instance_id}/status", nil, {'Authorization' => "Bearer #{token}"})
34
+ puts "Processes: #{JSON.pretty_generate(status['processes'])}"
35
+ end
36
+ end
37
+
38
+ def create(cloud_id, name, options)
39
+ sizes = {mini: 1, small: 2, medium: 4}
40
+ size = sizes[options.size.to_s.to_sym] || 1
41
+ data = {
42
+ name: name,
43
+ serviceProviderId: 'mar',
44
+ datacenterId: options.datacenter || 'eu-1',
45
+ config: {
46
+ runtimeSize: size,
47
+ runtimeType: 'app'
48
+ }
49
+ }
50
+ response = platform_client.post("/accounts/#{cloud_id}/instances", data)
51
+ puts response['id']
52
+ end
53
+
54
+ def restart(options)
55
+ instance_id = resolve_instance_id(options)
56
+ instance_data = instance_info(instance_id)
57
+ if instance_data
58
+ token = instance_data['authorizations'][0]['access_token']
59
+ client.post("/apps/#{instance_id}/restart", {}, nil, {'Authorization' => "Bearer #{token}"})
60
+ end
61
+
62
+ end
63
+
64
+ def logs(options)
65
+ offset = options.offset || 0
66
+ limit = options.limit || 100
67
+ stream = options.stream || nil
68
+
69
+ instance_id = resolve_instance_id(options)
70
+ instance_data = instance_info(instance_id)
71
+ if instance_data
72
+ token = instance_data['authorizations'][0]['access_token']
73
+ result = client.get("/apps/#{instance_id}/logs", {offset: offset, limit: limit}, {'Authorization' => "Bearer #{token}"})
74
+ result['results'].each do |r|
75
+ line = ''
76
+ line << "[#{r['time']}] " if options.timestamp == true
77
+ line << r['log']
78
+ puts line
79
+ end
80
+ end
81
+ rescue
82
+ abort("Error: can't show logs for this instance")
83
+ end
84
+
85
+ def scale(args, options)
86
+ instance_id = resolve_instance_id(options)
87
+ instance_data = instance_info(instance_id)
88
+ if instance_data
89
+ token = instance_data['authorizations'][0]['access_token']
90
+ app = client.get("/apps/#{instance_id}", nil, {'Authorization' => "Bearer #{token}"})
91
+ structure = app['structure']
92
+ scale = {}
93
+ args.each do |type|
94
+ arr = type.strip.split("=")
95
+ if arr[0] && arr[1]
96
+ raise ArgumentError.new("#{arr[0]} is not defined in Procfile") unless structure.has_key?(arr[0])
97
+ scale[arr[0]] = arr[1]
98
+ end
99
+ end
100
+ client.post("/apps/#{instance_id}/scale", scale, {}, {'Authorization' => "Bearer #{token}"})
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,41 @@
1
+ require 'qtc/client'
2
+ require_relative '../common'
3
+
4
+ module Qtc
5
+ module Cli
6
+ module Mar
7
+ class Base
8
+ include Cli::Common
9
+
10
+ protected
11
+
12
+ def resolve_instance_id(options)
13
+ if options.app.nil?
14
+ instance_id = extract_app_in_dir(options.remote)
15
+ else
16
+ instance_id = options.app
17
+ end
18
+ if instance_id.nil?
19
+ raise ArgumentError.new('Cannot resolve current app, please use --app APP')
20
+ end
21
+
22
+ instance_id
23
+ end
24
+
25
+ ##
26
+ # @return [Qtc::Client]
27
+ def client
28
+ if @client.nil?
29
+ @client = Qtc::Client.new(base_url)
30
+ end
31
+
32
+ @client
33
+ end
34
+
35
+ def base_url
36
+ ENV['QTC_MAR_URL'] || 'https://mar-eu-1.qtc.io/v1'
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,147 @@
1
+ require_relative 'apps'
2
+ require_relative 'domains'
3
+ require_relative 'ssl_certificates'
4
+ require_relative 'env'
5
+
6
+ command 'mar list' do |c|
7
+ c.syntax = 'qtc-cli mar list'
8
+ c.description = 'List all apps'
9
+ c.action do |args, options|
10
+ Qtc::Cli::Mar::Apps.new.list
11
+ end
12
+ end
13
+
14
+ command 'mar show' do |c|
15
+ c.syntax = 'qtc-cli mar show'
16
+ c.description = 'Show app details'
17
+ c.example 'Show app details for app with instance id: mar-eu-1-example', 'qtc-cli mar show --app mar-eu-1-example'
18
+ c.option '--app APP', String, 'App instance id'
19
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
20
+ c.action do |args, options|
21
+ Qtc::Cli::Mar::Apps.new.show(options)
22
+ end
23
+ end
24
+
25
+ command 'mar restart' do |c|
26
+ c.syntax = 'qtc-cli mar restart'
27
+ c.description = 'Restart app'
28
+ c.option '--app APP', String, 'App instance id'
29
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
30
+ c.action do |args, options|
31
+ Qtc::Cli::Mar::Apps.new.restart(options)
32
+ end
33
+ end
34
+
35
+ command 'mar create' do |c|
36
+ c.syntax = 'qtc-cli mar create CLOUD_ID NAME'
37
+ c.description = 'Create a new app instance'
38
+ c.option '--size SIZE', String, 'App runtime size'
39
+ c.option '--datacenter DATACENTER', String, 'Datacenter id'
40
+ c.action do |args, options|
41
+ raise ArgumentError.new('CLOUD_ID is required') if args[0].nil?
42
+ raise ArgumentError.new('NAME is required') if args[1].nil?
43
+ Qtc::Cli::Mar::Apps.new.create(args[0], args[1], options)
44
+ end
45
+ end
46
+
47
+
48
+ command 'mar scale' do |c|
49
+ c.syntax = 'qtc-cli mar scale KEY=VALUE'
50
+ c.description = 'Scale app processes'
51
+ c.option '--app APP', String, 'App instance id'
52
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
53
+ c.action do |args, options|
54
+ Qtc::Cli::Mar::Apps.new.scale(args, options)
55
+ end
56
+ end
57
+
58
+ command 'mar logs' do |c|
59
+ c.syntax = 'qtc-cli mar logs'
60
+ c.description = 'List app log entries'
61
+ c.option '--app APP', String, 'App instance id'
62
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
63
+ c.option '--timestamp', String, 'Include timestamp'
64
+ c.option '--stream', String, 'stdout or stderr'
65
+ c.option '--limit LIMIT', Integer, 'Limit'
66
+ c.option '--offset OFFSET', Integer, 'Offset'
67
+ c.action do |args, options|
68
+ Qtc::Cli::Mar::Apps.new.logs(options)
69
+ end
70
+ end
71
+
72
+ command 'mar domains' do |c|
73
+ c.syntax = 'qtc-cli mar domains'
74
+ c.description = 'List app domains'
75
+ c.option '--app APP', String, 'App instance id'
76
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
77
+ c.action do |args, options|
78
+ Qtc::Cli::Mar::Domains.new.list(options)
79
+ end
80
+ end
81
+
82
+ command 'mar domains:add' do |c|
83
+ c.syntax = 'qtc-cli mar domains:add DOMAIN'
84
+ c.description = 'Add custom domain to app'
85
+ c.option '--app APP', String, 'App instance id'
86
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
87
+ c.action do |args, options|
88
+ raise ArgumentError.new('DOMAIN is required') if args[0].nil?
89
+ Qtc::Cli::Mar::Domains.new.create(args[0], options)
90
+ end
91
+ end
92
+
93
+ command 'mar domains:remove' do |c|
94
+ c.syntax = 'qtc-cli domains:remove DOMAIN'
95
+ c.description = 'Remove custom domain from app'
96
+ c.option '--app APP', String, 'App instance id'
97
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
98
+ c.action do |args, options|
99
+ raise ArgumentError.new('DOMAIN is required') if args[0].nil?
100
+ Qtc::Cli::Mar::Domains.new.destroy(args[0], options)
101
+ end
102
+ end
103
+
104
+ command 'mar envs' do |c|
105
+ c.syntax = 'qtc-cli mar envs'
106
+ c.description = 'List app environment variables'
107
+ c.option '--app APP', String, 'App instance id'
108
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
109
+ c.action do |args, options|
110
+ Qtc::Cli::Mar::Env.new.show(options)
111
+ end
112
+ end
113
+
114
+ command 'mar envs:set' do |c|
115
+ c.syntax = 'qtc-cli mar envs:set KEY=value'
116
+ c.description = 'Set app environment variable'
117
+ c.option '--app APP', String, 'App instance id'
118
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
119
+ c.action do |args, options|
120
+ raise ArgumentError.new("You didn't specify any values") if args[0].nil?
121
+ Qtc::Cli::Mar::Env.new.set(args, options)
122
+ end
123
+ end
124
+
125
+ command 'mar ssl:add' do |c|
126
+ c.syntax = 'qtc-cli mar ssl:add --key=<path_to_pem> --cert=<path_to_crt>'
127
+ c.description = 'Add SSL certificate to app'
128
+ c.option '--app APP', String, 'App instance id'
129
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
130
+ c.option '--key PATH', String, 'Path to private key file'
131
+ c.option '--cert PATH', String, 'Path to certificate file'
132
+ c.action do |args, options|
133
+ raise ArgumentError.new("--key is required") unless options.key
134
+ raise ArgumentError.new("--cert is required") unless options.cert
135
+ Qtc::Cli::Mar::SslCertificates.new.create(options)
136
+ end
137
+ end
138
+
139
+ command 'mar ssl:remove' do |c|
140
+ c.syntax = 'qtc-cli mar remove-ssl-cert'
141
+ c.description = 'Remove SSL certificate from app'
142
+ c.option '--app APP', String, 'App instance id'
143
+ c.option '--remote REMOTE', String, 'Git remote to use, eg "staging"'
144
+ c.action do |args, options|
145
+ Qtc::Cli::Mar::SslCertificates.new.destroy(options)
146
+ end
147
+ end