envirobly 1.1.0 → 1.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4069ab1f0da67a7bc06444c1d32cef454c23924f125925f1bc00bcd56419b94f
4
- data.tar.gz: e5f5628338e7b9deda59a6c26f6e95b967f8ecbbfa0a1b41994aa3834f92a77a
3
+ metadata.gz: d0c82c3d281dbf388ec284da2fa021ff0156c1f31186ff5be11941da5f61dde3
4
+ data.tar.gz: 59d859fcf27af7159039c3ff989ec7680a1e026a7f9c3e10703fa23e0e21fa3c
5
5
  SHA512:
6
- metadata.gz: de515ea959bef33ba5a1e89ffa6862d3a8f116a8f4cab2249b97042e7a92e19020daeba4c5a93babbee793656f1f34b86850924cf97cb22b17f0a739333de4a1
7
- data.tar.gz: af5c4e4b6d08d1c08a06be9089a9e0f0d790915efafbf0cf0694a0e0ff90c68fbfdebdcb78c2921a3f7dd571561132968839832c0c5c5cb8be7a5b13b59afba0
6
+ metadata.gz: 64b90a90f4f60bafa98dc3900cf1c35f43a59c1236ec68a912e81a2bd7d1a72cb61c5e6cb95676d453128fe011203a7189c654b90e3e522a5fcdd40b11f827fd
7
+ data.tar.gz: df34ff8fb88ed79df45e741c1e031492f093f5556f858757c30ebbd828aa6ffb3e878461d656dd6752f2109903f4efaa58f97b5a97e1814e21d4447afb85284a
@@ -69,7 +69,7 @@ class Envirobly::AccessToken
69
69
  exit
70
70
  end
71
71
 
72
- api = Envirobly::Api.new(access_token: self)
72
+ api = Envirobly::Api.new(access_token: self, exit_on_error: false)
73
73
 
74
74
  # TODO: Eventually replace with custom `whoami` API that returns name, email...
75
75
  if api.list_accounts.success?
data/lib/envirobly/api.rb CHANGED
@@ -8,7 +8,8 @@ class Envirobly::Api
8
8
  USER_AGENT = "Envirobly CLI v#{Envirobly::VERSION}"
9
9
  CONTENT_TYPE = "application/json"
10
10
 
11
- def initialize(access_token: Envirobly::AccessToken.new)
11
+ def initialize(access_token: Envirobly::AccessToken.new, exit_on_error: true)
12
+ @exit_on_error = exit_on_error
12
13
  @access_token = access_token
13
14
  end
14
15
 
@@ -25,6 +26,10 @@ class Envirobly::Api
25
26
  post_as_json(api_v1_deployments_url, params:, headers: authorization_headers)
26
27
  end
27
28
 
29
+ def create_service_shell_connection(params)
30
+ post_as_json(api_v1_service_shell_connections_url, params:, headers: authorization_headers)
31
+ end
32
+
28
33
  def list_accounts
29
34
  get_as_json api_v1_accounts_url, headers: authorization_headers
30
35
  end
@@ -97,6 +102,10 @@ class Envirobly::Api
97
102
  api_url_for "v1/instance_types", query: "region=#{region}"
98
103
  end
99
104
 
105
+ def api_v1_service_shell_connections_url
106
+ api_url_for "v1/service_shell_connections"
107
+ end
108
+
100
109
  def api_url_for(path, query: nil)
101
110
  URI::HTTPS.build(host: HOST, path: "/api/#{path}", query:)
102
111
  end
@@ -117,11 +126,18 @@ class Envirobly::Api
117
126
  http.request(request).tap do |response|
118
127
  def response.object
119
128
  @json_parsed_body ||= JSON.parse(body)
129
+ rescue
130
+ @json_parsed_body = { error_message: body }
120
131
  end
121
132
 
122
133
  def response.success?
123
134
  (200..299).include?(code.to_i)
124
135
  end
136
+
137
+ if @exit_on_error && !response.success? && response.object["error_message"].present?
138
+ puts response.object["error_message"] # TODO: Replace with shell.say_error
139
+ exit 1
140
+ end
125
141
  end
126
142
  end
127
143
 
@@ -53,7 +53,7 @@ class Envirobly::Cli::Main < Envirobly::Base
53
53
  end
54
54
  end
55
55
 
56
- desc "instance_types [region]", "List instance types in a given region, including price and performance characteristics."
56
+ desc "instance_types [REGION]", "List instance types in the given region, including price and performance characteristics."
57
57
  def instance_types(region = nil)
58
58
  default_region = Envirobly::Defaults::Region.new(shell:)
59
59
  region = region.presence || default_region.require_if_none
@@ -80,48 +80,52 @@ class Envirobly::Cli::Main < Envirobly::Base
80
80
  TXT
81
81
  method_option :account_id, type: :numeric
82
82
  method_option :region, type: :string
83
- method_option :project, type: :string
83
+ method_option :project_id, type: :numeric
84
+ method_option :project_name, type: :string
84
85
  method_option :commit, type: :string, default: "HEAD"
85
86
  method_option :dry_run, type: :boolean, default: false
86
87
  def deploy(environ_name = nil)
87
88
  commit = Envirobly::Git::Commit.new options.commit
88
89
 
89
90
  unless commit.exists?
90
- say_error "Commit '#{commit.ref}' doesn't exist in this repository. Aborting."
91
+ say_error "Commit '#{commit.ref}' doesn't exist in this repository"
91
92
  exit 1
92
93
  end
93
94
 
94
95
  Envirobly::AccessToken.new(shell:).require!
95
96
 
96
- environ_name = environ_name.presence || commit.current_branch
97
- project_name = nil
98
- project_id = nil
99
-
100
- if options.project.present?
101
- if options.project =~ Envirobly::Defaults::Project.regexp
102
- project_id = $1.to_i
103
- else
104
- project_name = options.project
105
- end
106
- end
107
-
108
97
  deployment = Envirobly::Deployment.new(
109
98
  account_id: options.account_id,
110
99
  region: options.region,
111
- project_name:,
112
- environ_name:,
113
- project_id:,
100
+ project_id: options.project_id,
101
+ project_name: options.project_name,
102
+ environ_name: environ_name.presence || commit.current_branch,
114
103
  commit:,
115
104
  shell:
116
105
  )
117
106
  deployment.perform(dry_run: options.dry_run)
118
107
  end
119
108
 
120
- desc "pull", "Download build context"
109
+ desc "pull REGION BUCKET REF PATH", "Download build context. Used by Envirobly builders."
121
110
  def pull(region, bucket, ref, path)
122
111
  Envirobly::Duration.measure("Build context download took %s") do
123
- s3 = Envirobly::Aws::S3.new(region:, bucket:)
124
- s3.pull ref, path
112
+ Envirobly::Aws::S3.new(region:, bucket:).pull ref, path
125
113
  end
126
114
  end
115
+
116
+ desc "exec SERVICE_NAME [COMMAND] [ARG...]", <<~TXT
117
+ Start interactive service shell when launched without arguments or execute a one-off command.
118
+ Keep in mind, your container might not have a shell installed. In such cases you won't be able
119
+ to start an interactive session.
120
+ TXT
121
+ method_option :account_id, type: :numeric
122
+ method_option :project_id, type: :numeric
123
+ method_option :project_name, type: :string
124
+ method_option :environ_name, type: :string
125
+ method_option :instance_slot, type: :numeric, default: 0
126
+ method_option :shell, type: :string
127
+ method_option :user, type: :string
128
+ def exec(service_name, *command)
129
+ Envirobly::ContainerShell.new(service_name, command, options).connect
130
+ end
127
131
  end
@@ -0,0 +1,66 @@
1
+ class Envirobly::ContainerShell
2
+ CMD_TEMLATE =
3
+ "AWS_ACCESS_KEY_ID='%s' " +
4
+ "AWS_SECRET_ACCESS_KEY='%s' " +
5
+ "AWS_SESSION_TOKEN='%s' " +
6
+ "ssh -i %s " +
7
+ "envirobly-service@%s " +
8
+ "-o StrictHostKeyChecking=accept-new " +
9
+ "-o ProxyCommand='aws ec2-instance-connect open-tunnel --instance-id %s --region %s'"
10
+
11
+ def initialize(service_name, command, options)
12
+ @command = command
13
+ @options = options
14
+ commit = Envirobly::Git::Commit.new "HEAD"
15
+ @params = {
16
+ project: {
17
+ account_id: options.account_id || Envirobly::Defaults::Account.new.id,
18
+ name: options.project_name || File.basename(Dir.pwd), # TODO: Extract into Defaults::ProjectName
19
+ id: options.project_id
20
+ },
21
+ environ: { name: options.environ_name || commit.current_branch },
22
+ service: { name: service_name },
23
+ instance: { slot: options.instance_slot }
24
+ }
25
+
26
+ if options.project_name.blank? && options.account_id.blank? && options.project_id.blank?
27
+ @params[:project][:id] = Envirobly::Defaults::Project.new.id
28
+ end
29
+ end
30
+
31
+ def connect
32
+ api = Envirobly::Api.new
33
+ response = api.create_service_shell_connection @params
34
+ ssh_params = response.object
35
+
36
+ Tempfile.create do |tempkey|
37
+ tempkey.write ssh_params.fetch("instance").fetch("private_key")
38
+ tempkey.flush
39
+
40
+ cmd = sprintf(
41
+ CMD_TEMLATE,
42
+ ssh_params.fetch("open_tunnel_credentials").fetch("access_key_id"),
43
+ ssh_params.fetch("open_tunnel_credentials").fetch("secret_access_key"),
44
+ ssh_params.fetch("open_tunnel_credentials").fetch("session_token"),
45
+ tempkey.path,
46
+ ssh_params.fetch("instance").fetch("private_ipv4"),
47
+ ssh_params.fetch("instance").fetch("aws_id"),
48
+ ssh_params.fetch("region")
49
+ )
50
+
51
+ if @options.shell.present?
52
+ cmd = "ENVIROBLY_SERVICE_INTERACTIVE_SHELL='#{@options.shell}' #{cmd} -o SendEnv=ENVIROBLY_SERVICE_INTERACTIVE_SHELL"
53
+ end
54
+
55
+ if @options.user.present?
56
+ cmd = "ENVIROBLY_SERVICE_SHELL_USER='#{@options.user}' #{cmd} -o SendEnv=ENVIROBLY_SERVICE_SHELL_USER"
57
+ end
58
+
59
+ if @command.present?
60
+ cmd = "#{cmd} #{@command.join(" ")}"
61
+ end
62
+
63
+ system cmd
64
+ end
65
+ end
66
+ end
@@ -87,8 +87,7 @@ class Envirobly::Deployment
87
87
 
88
88
  Envirobly::Duration.measure do
89
89
  # Upload build context
90
- s3 = Envirobly::Aws::S3.new(bucket:, region:, credentials:)
91
- s3.push @commit
90
+ Envirobly::Aws::S3.new(bucket:, region:, credentials:).push @commit
92
91
 
93
92
  # Perform deployment
94
93
  api.put_as_json @deployment_url
@@ -1,3 +1,3 @@
1
1
  module Envirobly
2
- VERSION = "1.1.0"
2
+ VERSION = "1.3.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: envirobly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Starsi
@@ -168,6 +168,7 @@ files:
168
168
  - lib/envirobly/cli/main.rb
169
169
  - lib/envirobly/colorize.rb
170
170
  - lib/envirobly/config.rb
171
+ - lib/envirobly/container_shell.rb
171
172
  - lib/envirobly/default.rb
172
173
  - lib/envirobly/defaults.rb
173
174
  - lib/envirobly/defaults/account.rb