aptible-cli 0.14.1 → 0.15.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 +4 -4
- data/README.md +10 -1
- data/aptible-cli.gemspec +1 -0
- data/bin/aptible +9 -5
- data/lib/aptible/cli.rb +36 -0
- data/lib/aptible/cli/agent.rb +10 -6
- data/lib/aptible/cli/error.rb +6 -0
- data/lib/aptible/cli/formatter.rb +21 -0
- data/lib/aptible/cli/formatter/grouped_keyed_list.rb +54 -0
- data/lib/aptible/cli/formatter/keyed_list.rb +25 -0
- data/lib/aptible/cli/formatter/keyed_object.rb +16 -0
- data/lib/aptible/cli/formatter/list.rb +33 -0
- data/lib/aptible/cli/formatter/node.rb +8 -0
- data/lib/aptible/cli/formatter/object.rb +38 -0
- data/lib/aptible/cli/formatter/root.rb +46 -0
- data/lib/aptible/cli/formatter/value.rb +25 -0
- data/lib/aptible/cli/helpers/app.rb +1 -0
- data/lib/aptible/cli/helpers/database.rb +22 -6
- data/lib/aptible/cli/helpers/operation.rb +3 -2
- data/lib/aptible/cli/helpers/tunnel.rb +1 -3
- data/lib/aptible/cli/helpers/vhost.rb +9 -46
- data/lib/aptible/cli/renderer.rb +26 -0
- data/lib/aptible/cli/renderer/base.rb +8 -0
- data/lib/aptible/cli/renderer/json.rb +26 -0
- data/lib/aptible/cli/renderer/text.rb +99 -0
- data/lib/aptible/cli/resource_formatter.rb +136 -0
- data/lib/aptible/cli/subcommands/apps.rb +26 -14
- data/lib/aptible/cli/subcommands/backup.rb +22 -4
- data/lib/aptible/cli/subcommands/config.rb +15 -11
- data/lib/aptible/cli/subcommands/db.rb +82 -31
- data/lib/aptible/cli/subcommands/deploy.rb +1 -1
- data/lib/aptible/cli/subcommands/endpoints.rb +11 -8
- data/lib/aptible/cli/subcommands/operation.rb +2 -1
- data/lib/aptible/cli/subcommands/rebuild.rb +1 -1
- data/lib/aptible/cli/subcommands/restart.rb +1 -1
- data/lib/aptible/cli/subcommands/services.rb +8 -9
- data/lib/aptible/cli/version.rb +1 -1
- data/spec/aptible/cli/agent_spec.rb +11 -14
- data/spec/aptible/cli/formatter_spec.rb +4 -0
- data/spec/aptible/cli/renderer/json_spec.rb +63 -0
- data/spec/aptible/cli/renderer/text_spec.rb +150 -0
- data/spec/aptible/cli/resource_formatter_spec.rb +113 -0
- data/spec/aptible/cli/subcommands/apps_spec.rb +144 -28
- data/spec/aptible/cli/subcommands/backup_spec.rb +37 -16
- data/spec/aptible/cli/subcommands/config_spec.rb +95 -0
- data/spec/aptible/cli/subcommands/db_spec.rb +185 -93
- data/spec/aptible/cli/subcommands/endpoints_spec.rb +10 -8
- data/spec/aptible/cli/subcommands/operation_spec.rb +0 -1
- data/spec/aptible/cli/subcommands/rebuild_spec.rb +17 -0
- data/spec/aptible/cli/subcommands/services_spec.rb +8 -12
- data/spec/aptible/cli_spec.rb +31 -0
- data/spec/fabricators/account_fabricator.rb +11 -0
- data/spec/fabricators/app_fabricator.rb +15 -0
- data/spec/fabricators/configuration_fabricator.rb +8 -0
- data/spec/fabricators/database_image_fabricator.rb +17 -0
- data/spec/fabricators/operation_fabricator.rb +1 -0
- data/spec/fabricators/service_fabricator.rb +4 -0
- data/spec/spec_helper.rb +63 -1
- metadata +55 -4
- data/spec/aptible/cli/helpers/vhost_spec.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b0ef65d679c775ddb6867c82a3dcd03ff8b89242
|
4
|
+
data.tar.gz: 1f59dcda5ee8d9dc6c66adc1253442602c79c33c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52cb99978e5c6ec6fdb91d9bbd8903d26df80a1ba4d1aecc62c63ee47bc415c24f864541a2d35e4b0e293be5f3b84d2ce482a1a5c1c8a8324f30d529b8ff0abf
|
7
|
+
data.tar.gz: f50356c6dba2433f232b545415b887de601acc8f3e3ef9ec46d8dd9c0417c4e37dd31db3a2dd3cc2921cb3825822f9a5b894b37dbba5e7789c8fce22b76d4926
|
data/README.md
CHANGED
@@ -42,7 +42,7 @@ Commands:
|
|
42
42
|
aptible config:unset # Alias for config:rm
|
43
43
|
aptible db:backup HANDLE # Backup a database
|
44
44
|
aptible db:clone SOURCE DEST # Clone a database to create a new one
|
45
|
-
aptible db:create HANDLE[--type TYPE] [--container-size SIZE_MB] [--size SIZE_GB]
|
45
|
+
aptible db:create HANDLE [--type TYPE] [--version VERSION] [--container-size SIZE_MB] [--size SIZE_GB] # Create a new database
|
46
46
|
aptible db:deprovision HANDLE # Deprovision a database
|
47
47
|
aptible db:dump HANDLE # Dump a remote database to file
|
48
48
|
aptible db:execute HANDLE SQL_FILE # Executes sql against a database
|
@@ -51,6 +51,7 @@ Commands:
|
|
51
51
|
aptible db:restart HANDLE [--container-size SIZE_MB] [--size SIZE_GB] # Restart a database
|
52
52
|
aptible db:tunnel HANDLE # Create a local tunnel to a database
|
53
53
|
aptible db:url HANDLE # Display a database URL
|
54
|
+
aptible db:versions # List available database versions
|
54
55
|
aptible deploy [OPTIONS] [VAR1=VAL1] [VAR=VAL2] ... # Deploy an app
|
55
56
|
aptible domains # Print an app's current virtual domains - DEPRECATED
|
56
57
|
aptible endpoints:database:create DATABASE # Create a Database Endpoint
|
@@ -76,6 +77,14 @@ Commands:
|
|
76
77
|
```
|
77
78
|
<!-- END USAGE -->
|
78
79
|
|
80
|
+
### Output Format
|
81
|
+
|
82
|
+
By default, the Aptible CLI outputs data as unstructured text, designed for human consumption.
|
83
|
+
|
84
|
+
If you need to parse the output in another program, set the `APTIBLE_OUTPUT_FORMAT` environment variable to `json` when calling the Aptible CLI for JSON output.
|
85
|
+
|
86
|
+
The default format is `text`.
|
87
|
+
|
79
88
|
## Contributing
|
80
89
|
|
81
90
|
1. Fork the project.
|
data/aptible-cli.gemspec
CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_dependency 'term-ansicolor'
|
30
30
|
spec.add_dependency 'chronic_duration', '~> 0.10.6'
|
31
31
|
spec.add_dependency 'win32-process' if Gem.win_platform?
|
32
|
+
spec.add_dependency 'activesupport', '>= 4.0', '< 6.0'
|
32
33
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
33
34
|
spec.add_development_dependency 'aptible-tasks', '~> 0.5.8'
|
34
35
|
spec.add_development_dependency 'rake'
|
data/bin/aptible
CHANGED
@@ -10,10 +10,14 @@ end
|
|
10
10
|
begin
|
11
11
|
Aptible::CLI::Agent.start
|
12
12
|
rescue HyperResource::ClientError => e
|
13
|
-
if e.body['error'] == 'invalid_token'
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
m = if e.body['error'] == 'invalid_token'
|
14
|
+
'API authentication error: please run aptible login'
|
15
|
+
else
|
16
|
+
"An error occurred: #{e.body['message']}"
|
17
|
+
end
|
18
|
+
Aptible::CLI.logger.error(m)
|
19
|
+
exit 1
|
20
|
+
rescue Aptible::CLI::UserError => e
|
21
|
+
Aptible::CLI.logger.error e.message
|
18
22
|
exit 1
|
19
23
|
end
|
data/lib/aptible/cli.rb
CHANGED
@@ -1,7 +1,43 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
1
3
|
require 'aptible/cli/version'
|
2
4
|
require 'aptible/cli/agent'
|
5
|
+
require 'aptible/cli/error'
|
6
|
+
require 'aptible/cli/formatter'
|
7
|
+
require 'aptible/cli/renderer'
|
8
|
+
require 'aptible/cli/resource_formatter'
|
3
9
|
|
4
10
|
module Aptible
|
5
11
|
module CLI
|
12
|
+
class LogFormatter
|
13
|
+
include Term::ANSIColor
|
14
|
+
|
15
|
+
def call(severity, _, _, msg)
|
16
|
+
color = case severity
|
17
|
+
when 'DEBUG'
|
18
|
+
:no_color
|
19
|
+
when 'INFO'
|
20
|
+
:green
|
21
|
+
when 'WARN'
|
22
|
+
:yellow
|
23
|
+
when 'ERROR', 'FATAL'
|
24
|
+
:red
|
25
|
+
else
|
26
|
+
:no_color
|
27
|
+
end
|
28
|
+
|
29
|
+
"#{public_send(color, msg)}\n"
|
30
|
+
end
|
31
|
+
|
32
|
+
def no_color(msg)
|
33
|
+
msg
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.logger
|
38
|
+
@logger ||= Logger.new($stderr).tap do |l|
|
39
|
+
l.formatter = LogFormatter.new
|
40
|
+
end
|
41
|
+
end
|
6
42
|
end
|
7
43
|
end
|
data/lib/aptible/cli/agent.rb
CHANGED
@@ -68,7 +68,11 @@ module Aptible
|
|
68
68
|
|
69
69
|
desc 'version', 'Print Aptible CLI version'
|
70
70
|
def version
|
71
|
-
|
71
|
+
Formatter.render(Renderer.current) do |root|
|
72
|
+
root.keyed_object('version') do |node|
|
73
|
+
node.value('version', version_string)
|
74
|
+
end
|
75
|
+
end
|
72
76
|
end
|
73
77
|
|
74
78
|
desc 'login', 'Log in to Aptible'
|
@@ -111,19 +115,19 @@ module Aptible
|
|
111
115
|
end
|
112
116
|
|
113
117
|
save_token(token.access_token)
|
114
|
-
|
118
|
+
CLI.logger.info "Token written to #{token_file}"
|
115
119
|
|
116
120
|
lifetime_format = { units: 2, joiner: ', ' }
|
117
121
|
token_lifetime = (token.expires_at - token.created_at).round
|
118
122
|
expires_in = ChronicDuration.output(token_lifetime, lifetime_format)
|
119
|
-
|
120
|
-
|
123
|
+
CLI.logger.info "This token will expire after #{expires_in} " \
|
124
|
+
'(use --lifetime to customize)'
|
121
125
|
end
|
122
126
|
|
123
127
|
private
|
124
128
|
|
125
129
|
def deprecated(msg)
|
126
|
-
|
130
|
+
CLI.logger.warn([
|
127
131
|
"DEPRECATION NOTICE: #{msg}",
|
128
132
|
'Please contact support@aptible.com with any questions.'
|
129
133
|
].join("\n"))
|
@@ -147,7 +151,7 @@ module Aptible
|
|
147
151
|
now = Time.now.utc.to_i
|
148
152
|
|
149
153
|
if last_nag < now - nag_frequency
|
150
|
-
|
154
|
+
CLI.logger.warn([
|
151
155
|
'You have installed the Aptible CLI from source.',
|
152
156
|
'This is not recommended: some functionality may not work!',
|
153
157
|
'Review this support topic for more information:',
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require_relative 'formatter/node'
|
2
|
+
require_relative 'formatter/list'
|
3
|
+
require_relative 'formatter/keyed_list'
|
4
|
+
require_relative 'formatter/grouped_keyed_list'
|
5
|
+
require_relative 'formatter/object'
|
6
|
+
require_relative 'formatter/keyed_object'
|
7
|
+
require_relative 'formatter/root'
|
8
|
+
require_relative 'formatter/value'
|
9
|
+
|
10
|
+
module Aptible
|
11
|
+
module CLI
|
12
|
+
module Formatter
|
13
|
+
def self.render(renderer)
|
14
|
+
root = Root.new
|
15
|
+
yield root
|
16
|
+
out = renderer.render(root)
|
17
|
+
puts out if out
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Aptible
|
2
|
+
module CLI
|
3
|
+
module Formatter
|
4
|
+
class GroupedKeyedList < KeyedList
|
5
|
+
attr_reader :group
|
6
|
+
|
7
|
+
class InvalidGroup
|
8
|
+
def initialize(group)
|
9
|
+
m = 'group argument must be a string or a hash with one key ' \
|
10
|
+
"and a string value. #{group} is invalid"
|
11
|
+
super(m)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(group, y)
|
16
|
+
@group = group
|
17
|
+
validate_group!
|
18
|
+
super(y)
|
19
|
+
end
|
20
|
+
|
21
|
+
def groups
|
22
|
+
children.group_by(&grouper)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def grouper
|
28
|
+
case group
|
29
|
+
when String
|
30
|
+
lambda do |n|
|
31
|
+
n.children.fetch(group)
|
32
|
+
end
|
33
|
+
when Hash
|
34
|
+
first, second = group.to_a.first
|
35
|
+
lambda do |n|
|
36
|
+
n.children.fetch(first).children.fetch(second)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate_group!
|
42
|
+
return if group.is_a?(String)
|
43
|
+
if group.is_a?(Hash)
|
44
|
+
keys = group.keys
|
45
|
+
raise InvalidGroup, group if keys.size != 1
|
46
|
+
raise InvalidGroup, group unless group[keys.first].is_a?(String)
|
47
|
+
return
|
48
|
+
end
|
49
|
+
raise InvalidGroup(group)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Aptible
|
2
|
+
module CLI
|
3
|
+
module Formatter
|
4
|
+
class KeyedList < List
|
5
|
+
# KeyedList is a list of objects with one key that is more important
|
6
|
+
# than the others. Some renderers may opt to only display this key when
|
7
|
+
# rendering the list.
|
8
|
+
attr_reader :key
|
9
|
+
|
10
|
+
def initialize(key)
|
11
|
+
@key = key
|
12
|
+
super()
|
13
|
+
end
|
14
|
+
|
15
|
+
def value(_)
|
16
|
+
raise "not supported on #{self.class}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def list
|
20
|
+
raise "not supported on #{self.class}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Aptible
|
2
|
+
module CLI
|
3
|
+
module Formatter
|
4
|
+
class KeyedObject < Object
|
5
|
+
# KeyedObject is rendered as an Object, but flags a given key as being
|
6
|
+
# more important. Renderers may opt to only render this key.
|
7
|
+
attr_reader :key
|
8
|
+
|
9
|
+
def initialize(key)
|
10
|
+
@key = key
|
11
|
+
super()
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Aptible
|
2
|
+
module CLI
|
3
|
+
module Formatter
|
4
|
+
class List < Node
|
5
|
+
attr_reader :children
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@children = []
|
9
|
+
end
|
10
|
+
|
11
|
+
def value(s)
|
12
|
+
# TODO: Fail if block?
|
13
|
+
@children << Value.new(s)
|
14
|
+
nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def object
|
18
|
+
o = Object.new
|
19
|
+
yield o
|
20
|
+
@children << o
|
21
|
+
nil
|
22
|
+
end
|
23
|
+
|
24
|
+
def list
|
25
|
+
l = List.new
|
26
|
+
yield l
|
27
|
+
@children << l
|
28
|
+
nil
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Aptible
|
2
|
+
module CLI
|
3
|
+
module Formatter
|
4
|
+
class Object < Node
|
5
|
+
attr_reader :children
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@children = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def value(k, v)
|
12
|
+
assign_child(k, Value.new(v)) {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def object(k, &block)
|
16
|
+
assign_child(k, Object.new, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def keyed_object(k, object_key, &block)
|
20
|
+
assign_child(k, KeyedObject.new(object_key), &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def list(k, &block)
|
24
|
+
assign_child(k, List.new, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def assign_child(k, node)
|
30
|
+
raise "Overwriting keys (#{k}) is not allowed" if @children[k]
|
31
|
+
yield node
|
32
|
+
@children[k] = node
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Aptible
|
2
|
+
module CLI
|
3
|
+
module Formatter
|
4
|
+
class Root < Node
|
5
|
+
attr_reader :root
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@root = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def value(s)
|
12
|
+
assign_root(Value.new(s)) {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def object(&block)
|
16
|
+
assign_root(Object.new, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def keyed_object(key, &block)
|
20
|
+
assign_root(KeyedObject.new(key), &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def list(&block)
|
24
|
+
assign_root(List.new, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def keyed_list(key, &block)
|
28
|
+
assign_root(KeyedList.new(key), &block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def grouped_keyed_list(group, key, &block)
|
32
|
+
assign_root(GroupedKeyedList.new(group, key), &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def assign_root(node)
|
38
|
+
raise "root has already been initialized: #{@root.inspect}" if @root
|
39
|
+
yield node
|
40
|
+
@root = node
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Aptible
|
2
|
+
module CLI
|
3
|
+
module Formatter
|
4
|
+
class Value < Node
|
5
|
+
include Comparable
|
6
|
+
|
7
|
+
attr_reader :value
|
8
|
+
|
9
|
+
def initialize(value)
|
10
|
+
@value = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def <=>(other)
|
14
|
+
value <=> other.value
|
15
|
+
end
|
16
|
+
|
17
|
+
alias eql? ==
|
18
|
+
|
19
|
+
def hash
|
20
|
+
value.hash
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|