qtc-sdk 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -18
  3. data/.rspec +2 -0
  4. data/.travis.yml +7 -0
  5. data/Changelog.md +28 -23
  6. data/Gemfile +4 -4
  7. data/LICENSE.txt +22 -22
  8. data/README.md +42 -44
  9. data/Rakefile +1 -1
  10. data/bin/qtc-cli +13 -13
  11. data/lib/qtc-sdk.rb +1 -1
  12. data/lib/qtc/cli/commands.rb +15 -15
  13. data/lib/qtc/cli/common.rb +146 -146
  14. data/lib/qtc/cli/eds/base.rb +27 -27
  15. data/lib/qtc/cli/eds/commands.rb +20 -20
  16. data/lib/qtc/cli/eds/instances.rb +30 -30
  17. data/lib/qtc/cli/mar/apps.rb +116 -116
  18. data/lib/qtc/cli/mar/base.rb +60 -60
  19. data/lib/qtc/cli/mar/commands.rb +268 -266
  20. data/lib/qtc/cli/mar/debug.rb +94 -88
  21. data/lib/qtc/cli/mar/domains.rb +35 -35
  22. data/lib/qtc/cli/mar/env.rb +38 -38
  23. data/lib/qtc/cli/mar/repository.rb +24 -24
  24. data/lib/qtc/cli/mar/slugs.rb +80 -80
  25. data/lib/qtc/cli/mar/ssl_certificates.rb +40 -40
  26. data/lib/qtc/cli/mar/stack.rb +29 -29
  27. data/lib/qtc/cli/mdb/base.rb +47 -47
  28. data/lib/qtc/cli/mdb/commands.rb +43 -43
  29. data/lib/qtc/cli/mdb/instances.rb +79 -79
  30. data/lib/qtc/cli/platform/clouds.rb +33 -33
  31. data/lib/qtc/cli/platform/commands.rb +133 -132
  32. data/lib/qtc/cli/platform/datacenters.rb +23 -23
  33. data/lib/qtc/cli/platform/ssh_keys.rb +41 -41
  34. data/lib/qtc/cli/platform/user.rb +29 -25
  35. data/lib/qtc/cli/platform/vpn.rb +93 -93
  36. data/lib/qtc/client.rb +170 -170
  37. data/lib/qtc/eds/client.rb +116 -116
  38. data/lib/qtc/eds/collection.rb +124 -124
  39. data/lib/qtc/eds/user_collection.rb +13 -13
  40. data/lib/qtc/eds/usergroup_collection.rb +41 -41
  41. data/lib/qtc/errors.rb +13 -13
  42. data/lib/qtc/version.rb +3 -3
  43. data/qtc-sdk.gemspec +28 -28
  44. data/spec/spec_helper.rb +17 -0
  45. data/spec/unit/qtc/client_spec.rb +147 -147
  46. metadata +5 -3
@@ -1,88 +1,94 @@
1
- require_relative 'base'
2
- require 'open3'
3
-
4
- module Qtc
5
- module Cli
6
- class Mar::Debug < Mar::Base
7
-
8
- def local_debug(commands, options)
9
- app_home = File.realpath('.')
10
- docker_id = nil
11
- stack = options.stack || 'cedar-14'
12
- puts "-----> Starting to build MAR app locally"
13
-
14
- if options.clean == true && File.exists?("#{app_home}/slug.tgz")
15
- File.delete("#{app_home}/slug.tgz")
16
- end
17
-
18
- unless File.exists?("#{app_home}/slug.tgz")
19
- docker_id = build_slug(app_home, stack)
20
- else
21
- puts " Existing slug.tgz found, build not needed."
22
- end
23
- puts "-----> Starting app container"
24
- run_opts = [
25
- '-e PORT=5000',
26
- "-e STACK=#{stack}",
27
- '-e SLUG_URL=file:///tmp/fake_slug.tgz',
28
- '-p 5000',
29
- "-v #{app_home}/slug.tgz:/tmp/fake_slug.tgz"
30
- ]
31
- if File.exists?("#{app_home}/.env")
32
- run_opts << "--env-file=#{app_home}/.env"
33
- end
34
- if commands.size == 0
35
- cmd = 'start web'
36
- else
37
- cmd = commands.join(" ")
38
- end
39
-
40
- exec("docker run -it #{run_opts.join(" ")} qtcs/slugrunner:#{stack} #{cmd}")
41
- end
42
-
43
- def local_build_slug(options)
44
- stack = options.stack || 'cedar-14'
45
- app_home = File.realpath('.')
46
- puts "-----> Starting to build MAR app locally"
47
- build_slug(app_home, stack)
48
- end
49
-
50
- def build_slug(app_home, stack)
51
- docker_id = nil
52
- run_opts = ''
53
- if File.exists?("#{app_home}/.env")
54
- run_opts << "--env-file=#{app_home}/.env"
55
- end
56
- Open3.popen3("docker run -d #{run_opts} -v #{app_home}:/tmp/gitrepo:r qtcs/slugbuilder:#{stack}") {|stdin, stdout, stderr, wait_thr|
57
- docker_id = stdout.gets
58
- if docker_id
59
- docker_id.strip!
60
- else
61
- puts stderr.gets
62
- end
63
- exit_status = wait_thr.value
64
- unless exit_status.success?
65
- raise "ERROR: build failed to start"
66
- end
67
- }
68
- Open3.popen2('docker', 'attach', docker_id){|stdin, stdout, wait_thr|
69
- stdin.close
70
- while line = stdout.gets
71
- puts line
72
- end
73
- exit_status = wait_thr.value
74
- unless exit_status.success?
75
- raise "ERROR: build failed to complete"
76
- end
77
- }
78
- puts "-----> Extracting slug from build image to ./slug.tgz"
79
- system("docker cp #{docker_id}:/tmp/slug.tgz . > /dev/null")
80
-
81
- docker_id
82
- rescue => exc
83
- system("docker rm -f #{docker_id}") if docker_id
84
- raise exc
85
- end
86
- end
87
- end
88
- end
1
+ require_relative 'base'
2
+ require 'open3'
3
+
4
+ module Qtc
5
+ module Cli
6
+ class Mar::Debug < Mar::Base
7
+
8
+ def local_debug(commands, options)
9
+ app_home = File.realpath('.')
10
+ stack = options.stack || 'cedar-14'
11
+ branch = options.branch || 'master'
12
+ puts "-----> Starting to build MAR app locally"
13
+ puts " Using stack: #{stack}"
14
+ puts " Using git branch: #{branch}"
15
+
16
+ if options.clean == true && File.exists?("#{app_home}/slug.tgz")
17
+ File.delete("#{app_home}/slug.tgz")
18
+ end
19
+
20
+ unless File.exists?("#{app_home}/slug.tgz")
21
+ build_slug(app_home, stack, branch)
22
+ else
23
+ puts " Existing slug.tgz found, build not needed."
24
+ end
25
+ puts "-----> Starting app container"
26
+ run_opts = [
27
+ '-e PORT=5000',
28
+ "-e STACK=#{stack}",
29
+ '-e SLUG_URL=file:///tmp/fake_slug.tgz',
30
+ '-p 5000',
31
+ "-v #{app_home}/slug.tgz:/tmp/fake_slug.tgz"
32
+ ]
33
+ if File.exists?("#{app_home}/.env")
34
+ run_opts << "--env-file=#{app_home}/.env"
35
+ end
36
+ if commands.size == 0
37
+ cmd = 'start web'
38
+ else
39
+ cmd = commands.join(" ")
40
+ end
41
+
42
+ exec("docker run -it #{run_opts.join(" ")} qtcs/slugrunner:#{stack} #{cmd}")
43
+ end
44
+
45
+ def local_build_slug(options)
46
+ stack = options.stack || 'cedar-14'
47
+ branch = options.branch || 'master'
48
+ app_home = File.realpath('.')
49
+ puts "-----> Starting to build MAR app locally"
50
+ puts " Using stack: #{stack}"
51
+ puts " Using git branch: #{branch}"
52
+ build_slug(app_home, stack, branch)
53
+ end
54
+
55
+ def build_slug(app_home, stack, branch)
56
+ docker_id = nil
57
+ run_opts = '-i -a stdin'
58
+ if File.exists?("#{app_home}/.env")
59
+ run_opts << "--env-file=#{app_home}/.env"
60
+ end
61
+ Open3.popen3("git archive #{branch} | docker run #{run_opts} qtcs/slugbuilder:#{stack}") {|stdin, stdout, stderr, wait_thr|
62
+ stdin.close
63
+ docker_id = stdout.gets
64
+ if docker_id
65
+ docker_id.strip!
66
+ else
67
+ puts stderr.gets
68
+ end
69
+ exit_status = wait_thr.value
70
+ unless exit_status.success?
71
+ raise "ERROR: build failed to start"
72
+ end
73
+ }
74
+ Open3.popen2('docker', 'attach', docker_id){|stdin, stdout, wait_thr|
75
+ stdin.close
76
+ while line = stdout.gets
77
+ puts line
78
+ end
79
+ exit_status = wait_thr.value
80
+ unless exit_status.success?
81
+ raise "ERROR: build failed to complete"
82
+ end
83
+ }
84
+ puts "-----> Extracting slug from build image to ./slug.tgz"
85
+ system("docker cp #{docker_id}:/tmp/slug.tgz . > /dev/null")
86
+
87
+ docker_id
88
+ rescue => exc
89
+ system("docker rm -f #{docker_id}") if docker_id
90
+ raise exc
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,35 +1,35 @@
1
- require_relative 'base'
2
-
3
- module Qtc
4
- module Cli
5
- class Mar::Domains < Mar::Base
6
-
7
- def list(options)
8
- instance_id = resolve_instance_id(options)
9
- instance_data = instance_info(instance_id)
10
- if instance_data
11
- result = client.get("/apps/#{instance_id}/domains", nil, {'Authorization' => "Bearer #{current_cloud_token}"})
12
- result['results'].each do |r|
13
- print color("* #{r['name']}", :bold)
14
- end
15
- end
16
- end
17
-
18
- def create(name, options)
19
- instance_id = resolve_instance_id(options)
20
- instance_data = instance_info(instance_id)
21
- if instance_data
22
- client.post("/apps/#{instance_id}/domains", {name: name}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
- end
24
- end
25
-
26
- def destroy(name, options)
27
- instance_id = resolve_instance_id(options)
28
- instance_data = instance_info(instance_id)
29
- if instance_data
30
- client.delete("/apps/#{instance_id}/domains/#{name}", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
- end
32
- end
33
- end
34
- end
35
- end
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Mar::Domains < Mar::Base
6
+
7
+ def list(options)
8
+ instance_id = resolve_instance_id(options)
9
+ instance_data = instance_info(instance_id)
10
+ if instance_data
11
+ result = client.get("/apps/#{instance_id}/domains", nil, {'Authorization' => "Bearer #{current_cloud_token}"})
12
+ result['results'].each do |r|
13
+ print color("* #{r['name']}", :bold)
14
+ end
15
+ end
16
+ end
17
+
18
+ def create(name, options)
19
+ instance_id = resolve_instance_id(options)
20
+ instance_data = instance_info(instance_id)
21
+ if instance_data
22
+ client.post("/apps/#{instance_id}/domains", {name: name}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
+ end
24
+ end
25
+
26
+ def destroy(name, options)
27
+ instance_id = resolve_instance_id(options)
28
+ instance_data = instance_info(instance_id)
29
+ if instance_data
30
+ client.delete("/apps/#{instance_id}/domains/#{name}", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,38 +1,38 @@
1
- require_relative 'base'
2
-
3
- module Qtc
4
- module Cli
5
- class Mar::Env < Mar::Base
6
-
7
- def set(vars, options)
8
- instance_id = resolve_instance_id(options)
9
- env_vars = {}
10
- vars.each do |type|
11
- arr = type.strip.split('=', 2)
12
- if arr[0]
13
- if arr[1].nil? || arr[1] == ''
14
- env_vars[arr[0]] = nil
15
- else
16
- env_vars[arr[0]] = arr[1]
17
- end
18
- end
19
- end
20
- instance_data = instance_info(instance_id)
21
- if instance_data
22
- client.put("/apps/#{instance_id}/env_vars", env_vars, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
- end
24
- end
25
-
26
- def show(options)
27
- instance_id = resolve_instance_id(options)
28
- instance_data = instance_info(instance_id)
29
- if instance_data
30
- env_vars = client.get("/apps/#{instance_id}/env_vars", {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
- env_vars.each do |key, value|
32
- puts "#{key}=#{value}"
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Mar::Env < Mar::Base
6
+
7
+ def set(vars, options)
8
+ instance_id = resolve_instance_id(options)
9
+ env_vars = {}
10
+ vars.each do |type|
11
+ arr = type.strip.split('=', 2)
12
+ if arr[0]
13
+ if arr[1].nil? || arr[1] == ''
14
+ env_vars[arr[0]] = nil
15
+ else
16
+ env_vars[arr[0]] = arr[1]
17
+ end
18
+ end
19
+ end
20
+ instance_data = instance_info(instance_id)
21
+ if instance_data
22
+ client.put("/apps/#{instance_id}/env_vars", env_vars, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
+ end
24
+ end
25
+
26
+ def show(options)
27
+ instance_id = resolve_instance_id(options)
28
+ instance_data = instance_info(instance_id)
29
+ if instance_data
30
+ env_vars = client.get("/apps/#{instance_id}/env_vars", {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
+ env_vars.each do |key, value|
32
+ puts "#{key}=#{value}"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,24 +1,24 @@
1
- require_relative 'base'
2
-
3
- module Qtc
4
- module Cli
5
- class Mar::Repository < Mar::Base
6
-
7
- def purge_cache(options)
8
- instance_id = resolve_instance_id(options)
9
- instance_data = instance_info(instance_id)
10
- if instance_data
11
- client.delete("/apps/#{instance_id}/build_cache", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
12
- end
13
- end
14
-
15
- def reset(options)
16
- instance_id = resolve_instance_id(options)
17
- instance_data = instance_info(instance_id)
18
- if instance_data
19
- client.delete("/apps/#{instance_id}/repository", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
20
- end
21
- end
22
- end
23
- end
24
- end
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Mar::Repository < Mar::Base
6
+
7
+ def purge_cache(options)
8
+ instance_id = resolve_instance_id(options)
9
+ instance_data = instance_info(instance_id)
10
+ if instance_data
11
+ client.delete("/apps/#{instance_id}/build_cache", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
12
+ end
13
+ end
14
+
15
+ def reset(options)
16
+ instance_id = resolve_instance_id(options)
17
+ instance_data = instance_info(instance_id)
18
+ if instance_data
19
+ client.delete("/apps/#{instance_id}/repository", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,80 +1,80 @@
1
- require_relative 'base'
2
-
3
- require 'yaml'
4
- require 'fileutils'
5
- require 'httpclient'
6
- require 'net/http'
7
-
8
- module Qtc
9
- module Cli
10
- class Mar::Slugs < Mar::Base
11
-
12
- def list(options)
13
- instance_id = resolve_instance_id(options)
14
- slugs = client.get("/apps/#{instance_id}/slugs/", {}, {'Authorization' => "Bearer #{current_cloud_token}"})
15
- if slugs && slugs['results'].size > 0
16
- template = "%-20.20s %-30.30s %-30.30s"
17
- puts template % ["TAG", "CREATED", "DEPLOYED"]
18
- slugs['results'].each do |slug|
19
- puts template % [slug['tag'], slug['createdAt'], slug['deployedAt']]
20
- end
21
- end
22
- end
23
-
24
- def remove(slug_id, options)
25
- instance_id = resolve_instance_id(options)
26
- client.delete("/apps/#{instance_id}/slugs/#{slug_id}", {}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
27
- end
28
-
29
- def upload(options)
30
- instance_id = resolve_instance_id(options)
31
-
32
- slug = create_slug(instance_id, options)
33
- upload_uri = URI(slug['blob']['url'])
34
- puts "Starting slug upload, if your slug is large this may take a while"
35
- # todo Would be nice to have some sort of progress indication...
36
- begin
37
- open(File.new(options.slug), 'rb') do |io|
38
- aws_client = Net::HTTP.new(upload_uri.host)
39
- req = Net::HTTP::Put.new(upload_uri.request_uri)
40
- req.content_length = io.size
41
- req.body_stream = io
42
- req['Content-Type'] = 'application/octet-stream'
43
-
44
- aws_client.request(req)
45
- end
46
- rescue => exc
47
- puts "Slug upload failed:#{exc.to_s}"
48
- raise StandardError "Slug upload failed!"
49
- end
50
- puts "Slug uploaded successfully, you may now deploy it using commit tag: #{slug['tag']}"
51
- end
52
-
53
- def deploy(slug_id, options)
54
- instance_id = resolve_instance_id(options)
55
- client.post("/apps/#{instance_id}/slugs/#{slug_id}/deploy", {}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
56
- end
57
-
58
- def create_slug(instance_id, options)
59
- process_types = resolve_proc_types(options)
60
- data = {
61
- tag: options.tag,
62
- process_types: process_types
63
- }
64
- client.post("/apps/#{instance_id}/slugs", data, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
65
- end
66
-
67
- def resolve_proc_types(options)
68
- if options.procfile
69
- procfile_hash = {}
70
- procfile = YAML.load(File.read(options.procfile), :encoding => 'utf-8')
71
- procfile_hash.merge!(procfile) if procfile
72
- procfile_hash
73
- else
74
- raise StandardError 'Procfile must be given'
75
- end
76
- end
77
- end
78
- end
79
- end
80
-
1
+ require_relative 'base'
2
+
3
+ require 'yaml'
4
+ require 'fileutils'
5
+ require 'httpclient'
6
+ require 'net/http'
7
+
8
+ module Qtc
9
+ module Cli
10
+ class Mar::Slugs < Mar::Base
11
+
12
+ def list(options)
13
+ instance_id = resolve_instance_id(options)
14
+ slugs = client.get("/apps/#{instance_id}/slugs/", {}, {'Authorization' => "Bearer #{current_cloud_token}"})
15
+ if slugs && slugs['results'].size > 0
16
+ template = "%-20.20s %-30.30s %-30.30s"
17
+ puts template % ["TAG", "CREATED", "DEPLOYED"]
18
+ slugs['results'].each do |slug|
19
+ puts template % [slug['tag'], slug['createdAt'], slug['deployedAt']]
20
+ end
21
+ end
22
+ end
23
+
24
+ def remove(slug_id, options)
25
+ instance_id = resolve_instance_id(options)
26
+ client.delete("/apps/#{instance_id}/slugs/#{slug_id}", {}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
27
+ end
28
+
29
+ def upload(options)
30
+ instance_id = resolve_instance_id(options)
31
+
32
+ slug = create_slug(instance_id, options)
33
+ upload_uri = URI(slug['blob']['url'])
34
+ puts "Starting slug upload, if your slug is large this may take a while"
35
+ # todo Would be nice to have some sort of progress indication...
36
+ begin
37
+ open(File.new(options.slug), 'rb') do |io|
38
+ aws_client = Net::HTTP.new(upload_uri.host)
39
+ req = Net::HTTP::Put.new(upload_uri.request_uri)
40
+ req.content_length = io.size
41
+ req.body_stream = io
42
+ req['Content-Type'] = 'application/octet-stream'
43
+
44
+ aws_client.request(req)
45
+ end
46
+ rescue => exc
47
+ puts "Slug upload failed:#{exc.to_s}"
48
+ raise StandardError "Slug upload failed!"
49
+ end
50
+ puts "Slug uploaded successfully, you may now deploy it using commit tag: #{slug['tag']}"
51
+ end
52
+
53
+ def deploy(slug_id, options)
54
+ instance_id = resolve_instance_id(options)
55
+ client.post("/apps/#{instance_id}/slugs/#{slug_id}/deploy", {}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
56
+ end
57
+
58
+ def create_slug(instance_id, options)
59
+ process_types = resolve_proc_types(options)
60
+ data = {
61
+ tag: options.tag,
62
+ process_types: process_types
63
+ }
64
+ client.post("/apps/#{instance_id}/slugs", data, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
65
+ end
66
+
67
+ def resolve_proc_types(options)
68
+ if options.procfile
69
+ procfile_hash = {}
70
+ procfile = YAML.load(File.read(options.procfile), :encoding => 'utf-8')
71
+ procfile_hash.merge!(procfile) if procfile
72
+ procfile_hash
73
+ else
74
+ raise StandardError 'Procfile must be given'
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+