MuranoCLI 3.0.1 → 3.0.2
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/.agignore +1 -0
- data/.rubocop.yml +67 -5
- data/Gemfile +6 -3
- data/MuranoCLI.gemspec +14 -10
- data/README.markdown +299 -126
- data/Rakefile +6 -1
- data/bin/murano +2 -2
- data/docs/completions/murano_completion-bash +93 -0
- data/lib/MrMurano.rb +19 -2
- data/lib/MrMurano/Business.rb +22 -19
- data/lib/MrMurano/Config.rb +19 -9
- data/lib/MrMurano/Content.rb +4 -4
- data/lib/MrMurano/Exchange-Element.rb +99 -0
- data/lib/MrMurano/Exchange.rb +137 -0
- data/lib/MrMurano/Gateway.rb +9 -9
- data/lib/MrMurano/Keystore.rb +4 -2
- data/lib/MrMurano/ReCommander.rb +3 -5
- data/lib/MrMurano/Solution-ServiceConfig.rb +12 -12
- data/lib/MrMurano/Solution-Services.rb +15 -14
- data/lib/MrMurano/Solution-Users.rb +2 -2
- data/lib/MrMurano/Solution.rb +43 -49
- data/lib/MrMurano/SolutionId.rb +28 -28
- data/lib/MrMurano/SyncUpDown.rb +32 -22
- data/lib/MrMurano/Webservice-Endpoint.rb +2 -1
- data/lib/MrMurano/Webservice.rb +5 -5
- data/lib/MrMurano/commands.rb +2 -1
- data/lib/MrMurano/commands/business.rb +21 -19
- data/lib/MrMurano/commands/domain.rb +16 -2
- data/lib/MrMurano/commands/exchange.rb +272 -0
- data/lib/MrMurano/commands/globals.rb +17 -1
- data/lib/MrMurano/commands/init.rb +3 -3
- data/lib/MrMurano/commands/link.rb +16 -16
- data/lib/MrMurano/commands/postgresql.rb +2 -2
- data/lib/MrMurano/commands/show.rb +13 -7
- data/lib/MrMurano/commands/solution.rb +23 -17
- data/lib/MrMurano/commands/solution_picker.rb +49 -44
- data/lib/MrMurano/commands/sync.rb +2 -1
- data/lib/MrMurano/commands/timeseries.rb +2 -2
- data/lib/MrMurano/commands/tsdb.rb +2 -2
- data/lib/MrMurano/hash.rb +19 -7
- data/lib/MrMurano/http.rb +12 -2
- data/lib/MrMurano/orderedhash.rb +200 -0
- data/lib/MrMurano/spec_commander.rb +98 -0
- data/lib/MrMurano/verbosing.rb +2 -2
- data/lib/MrMurano/version.rb +2 -2
- data/spec/Business_spec.rb +8 -6
- data/spec/Solution-ServiceConfig_spec.rb +1 -1
- data/spec/SyncUpDown_spec.rb +6 -6
- data/spec/_workspace.rb +9 -4
- data/spec/cmd_business_spec.rb +8 -2
- data/spec/cmd_common.rb +266 -25
- data/spec/cmd_exchange_spec.rb +118 -0
- data/spec/cmd_help_spec.rb +54 -13
- data/spec/cmd_init_spec.rb +1 -12
- data/spec/cmd_link_spec.rb +94 -72
- data/spec/spec_helper.rb +11 -16
- metadata +23 -17
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.
|
1
|
+
# Last Modified: 2017.09.07 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -13,6 +13,7 @@ def sync_add_options(c, locale)
|
|
13
13
|
c.option '--[no-]delete', %(Don't delete things from #{locale})
|
14
14
|
c.option '--[no-]create', %(Don't create things on #{locale})
|
15
15
|
c.option '--[no-]update', %(Don't update things on #{locale})
|
16
|
+
c.option '--ignore-errors', %(Don't die on sync errors)
|
16
17
|
end
|
17
18
|
|
18
19
|
def syncdown_files(options, args=nil)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.
|
1
|
+
# Last Modified: 2017.09.11 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -11,7 +11,7 @@ require 'MrMurano/Solution-ServiceConfig'
|
|
11
11
|
|
12
12
|
module MrMurano
|
13
13
|
class Timeseries < ServiceConfig
|
14
|
-
def initialize(
|
14
|
+
def initialize(api_id=nil)
|
15
15
|
# FIXME/2017-07-03: What soln types have timeseries?
|
16
16
|
@solntype = 'application.id'
|
17
17
|
super
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.
|
1
|
+
# Last Modified: 2017.09.11 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -13,7 +13,7 @@ require 'MrMurano/SubCmdGroupContext'
|
|
13
13
|
module MrMurano
|
14
14
|
module ServiceConfigs
|
15
15
|
class Tsdb < ServiceConfig
|
16
|
-
def initialize(
|
16
|
+
def initialize(api_id=nil)
|
17
17
|
# FIXME/2017-07-03: What soln types have TSDBs?
|
18
18
|
@solntype = 'application.id'
|
19
19
|
super
|
data/lib/MrMurano/hash.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
# Last Modified: 2017.
|
1
|
+
# Last Modified: 2017.09.07 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
5
5
|
# License: MIT. See LICENSE.txt.
|
6
6
|
# vim:tw=0:ts=2:sw=2:et:ai
|
7
7
|
|
8
|
-
require 'orderedhash'
|
8
|
+
require 'MrMurano/orderedhash'
|
9
9
|
|
10
10
|
class Hash
|
11
11
|
# From:
|
@@ -73,9 +73,10 @@ def elevate_hash(hsh)
|
|
73
73
|
end
|
74
74
|
# build a hash where the default is 'false' instead of 'nil'
|
75
75
|
Hash.new(false).merge(Hash.transform_keys_to_symbols(hsh))
|
76
|
-
# 2017-
|
77
|
-
#
|
78
|
-
#
|
76
|
+
# 2017-09-07: Note that after elevate_hash, the Hash returns
|
77
|
+
# false on unknown keys. This is because of the parameter to
|
78
|
+
# new: Hash.new(false). Unknown keys would return nil before,
|
79
|
+
# but after, they return false. E.g.,
|
79
80
|
#
|
80
81
|
# (byeebug) options
|
81
82
|
# {:delete=>false, :create=>true, :update=>false}
|
@@ -89,8 +90,6 @@ def elevate_hash(hsh)
|
|
89
90
|
# false
|
90
91
|
# (byeebug) options
|
91
92
|
# {:delete=>false, :create=>true, :update=>false, :fff=>nil}
|
92
|
-
#
|
93
|
-
# Work around is to test with hash.key?
|
94
93
|
end
|
95
94
|
|
96
95
|
##
|
@@ -108,3 +107,16 @@ def ensure_array(item)
|
|
108
107
|
end
|
109
108
|
end
|
110
109
|
|
110
|
+
module HashInit
|
111
|
+
def initialize(*hash)
|
112
|
+
return unless hash.length == 1 && hash.first.is_a?(Hash)
|
113
|
+
hash.first.each do |key, val|
|
114
|
+
if respond_to? key
|
115
|
+
send("#{key}=", val)
|
116
|
+
else
|
117
|
+
$stderr.puts %(HashInit: missing hash key "#{key}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
data/lib/MrMurano/http.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.24 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -84,7 +84,17 @@ module MrMurano
|
|
84
84
|
if !defined?(@http) || @http.nil?
|
85
85
|
@http = Net::HTTP.new(uri.host, uri.port)
|
86
86
|
@http.use_ssl = true
|
87
|
-
|
87
|
+
begin
|
88
|
+
@http.start
|
89
|
+
rescue SocketError => err
|
90
|
+
# E.g., "error: Failed to open TCP connection to true:443
|
91
|
+
# (Hostname not known: true)."
|
92
|
+
error %(Net socket error: #{err.message})
|
93
|
+
exit 2
|
94
|
+
rescue StandardError => err
|
95
|
+
error %(Net request failed: #{err.message})
|
96
|
+
exit 2
|
97
|
+
end
|
88
98
|
end
|
89
99
|
@http
|
90
100
|
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
|
2
|
+
# AUTHOR
|
3
|
+
# jan molic /mig/at/1984/dot/cz/
|
4
|
+
#
|
5
|
+
# DESCRIPTION
|
6
|
+
# Hash with preserved order and some array-like extensions
|
7
|
+
# Public domain.
|
8
|
+
#
|
9
|
+
# THANKS
|
10
|
+
# Andrew Johnson for his suggestions and fixes of Hash[],
|
11
|
+
# merge, to_a, inspect and shift
|
12
|
+
class OrderedHash < ::Hash
|
13
|
+
attr_accessor :order
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def [] *args
|
17
|
+
hsh = OrderedHash.new
|
18
|
+
if Hash === args[0]
|
19
|
+
hsh.replace args[0]
|
20
|
+
elsif (args.size % 2) != 0
|
21
|
+
raise ArgumentError, "odd number of elements for Hash"
|
22
|
+
else
|
23
|
+
0.step(args.size - 1, 2) do |a|
|
24
|
+
b = a + 1
|
25
|
+
hsh[args[a]] = args[b]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
hsh
|
29
|
+
end
|
30
|
+
end
|
31
|
+
def initialize(*a, &b)
|
32
|
+
super
|
33
|
+
@order = []
|
34
|
+
end
|
35
|
+
def store_only a,b
|
36
|
+
store a,b
|
37
|
+
end
|
38
|
+
alias orig_store store
|
39
|
+
def store a,b
|
40
|
+
@order.push a unless has_key? a
|
41
|
+
super a,b
|
42
|
+
end
|
43
|
+
alias []= store
|
44
|
+
def == hsh2
|
45
|
+
return false if @order != hsh2.order
|
46
|
+
super hsh2
|
47
|
+
end
|
48
|
+
def clear
|
49
|
+
@order = []
|
50
|
+
super
|
51
|
+
end
|
52
|
+
def delete key
|
53
|
+
@order.delete key
|
54
|
+
super
|
55
|
+
end
|
56
|
+
def each_key
|
57
|
+
@order.each { |k| yield k }
|
58
|
+
self
|
59
|
+
end
|
60
|
+
def each_value
|
61
|
+
@order.each { |k| yield self[k] }
|
62
|
+
self
|
63
|
+
end
|
64
|
+
def each
|
65
|
+
@order.each { |k| yield k,self[k] }
|
66
|
+
self
|
67
|
+
end
|
68
|
+
alias each_pair each
|
69
|
+
def delete_if
|
70
|
+
@order.clone.each { |k|
|
71
|
+
delete k if yield(k)
|
72
|
+
}
|
73
|
+
self
|
74
|
+
end
|
75
|
+
def values
|
76
|
+
ary = []
|
77
|
+
@order.each { |k| ary.push self[k] }
|
78
|
+
ary
|
79
|
+
end
|
80
|
+
def keys
|
81
|
+
@order
|
82
|
+
end
|
83
|
+
def first
|
84
|
+
{@order.first => self[@order.first]}
|
85
|
+
end
|
86
|
+
def last
|
87
|
+
{@order.last => self[@order.last]}
|
88
|
+
end
|
89
|
+
def invert
|
90
|
+
hsh2 = Hash.new
|
91
|
+
@order.each { |k| hsh2[self[k]] = k }
|
92
|
+
hsh2
|
93
|
+
end
|
94
|
+
def reject &block
|
95
|
+
self.dup.delete_if(&block)
|
96
|
+
end
|
97
|
+
def reject! &block
|
98
|
+
hsh2 = reject(&block)
|
99
|
+
self == hsh2 ? nil : hsh2
|
100
|
+
end
|
101
|
+
def replace hsh2
|
102
|
+
@order = hsh2.keys
|
103
|
+
super hsh2
|
104
|
+
end
|
105
|
+
def shift
|
106
|
+
key = @order.first
|
107
|
+
key ? [key,delete(key)] : super
|
108
|
+
end
|
109
|
+
def unshift k,v
|
110
|
+
unless self.include? k
|
111
|
+
@order.unshift k
|
112
|
+
orig_store(k,v)
|
113
|
+
true
|
114
|
+
else
|
115
|
+
false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
def push k,v
|
119
|
+
unless self.include? k
|
120
|
+
@order.push k
|
121
|
+
orig_store(k,v)
|
122
|
+
true
|
123
|
+
else
|
124
|
+
false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
def pop
|
128
|
+
key = @order.last
|
129
|
+
key ? [key,delete(key)] : nil
|
130
|
+
end
|
131
|
+
def to_a
|
132
|
+
ary = []
|
133
|
+
each { |k,v| ary << [k,v] }
|
134
|
+
ary
|
135
|
+
end
|
136
|
+
def to_s
|
137
|
+
self.to_a.to_s
|
138
|
+
end
|
139
|
+
def inspect
|
140
|
+
ary = []
|
141
|
+
each {|k,v| ary << k.inspect + "=>" + v.inspect}
|
142
|
+
'{' + ary.join(", ") + '}'
|
143
|
+
end
|
144
|
+
def update hsh2
|
145
|
+
hsh2.each { |k,v| self[k] = v }
|
146
|
+
self
|
147
|
+
end
|
148
|
+
alias :merge! update
|
149
|
+
def merge hsh2
|
150
|
+
self.dup update(hsh2)
|
151
|
+
end
|
152
|
+
def select
|
153
|
+
ary = []
|
154
|
+
each { |k,v| ary << [k,v] if yield k,v }
|
155
|
+
ary
|
156
|
+
end
|
157
|
+
def class
|
158
|
+
Hash
|
159
|
+
end
|
160
|
+
def __class__
|
161
|
+
OrderedHash
|
162
|
+
end
|
163
|
+
|
164
|
+
attr_accessor "to_yaml_style"
|
165
|
+
def yaml_inline= bool
|
166
|
+
if respond_to?("to_yaml_style")
|
167
|
+
self.to_yaml_style = :inline
|
168
|
+
else
|
169
|
+
unless defined? @__yaml_inline_meth
|
170
|
+
@__yaml_inline_meth =
|
171
|
+
lambda {|opts|
|
172
|
+
YAML::quick_emit(object_id, opts) {|emitter|
|
173
|
+
emitter << '{ ' << map{|kv| kv.join ': '}.join(', ') << ' }'
|
174
|
+
}
|
175
|
+
}
|
176
|
+
class << self
|
177
|
+
def to_yaml opts = {}
|
178
|
+
begin
|
179
|
+
@__yaml_inline ? @__yaml_inline_meth[ opts ] : super
|
180
|
+
rescue
|
181
|
+
@to_yaml_style = :inline
|
182
|
+
super
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
@__yaml_inline = bool
|
189
|
+
end
|
190
|
+
def yaml_inline!() self.yaml_inline = true end
|
191
|
+
|
192
|
+
def each_with_index
|
193
|
+
@order.each_with_index { |k, index| yield k, self[k], index }
|
194
|
+
self
|
195
|
+
end
|
196
|
+
end # class OrderedHash
|
197
|
+
|
198
|
+
def OrderedHash(*a, &b)
|
199
|
+
OrderedHash.new(*a, &b)
|
200
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Last Modified: 2017.08.30 /coding: utf-8
|
3
|
+
# frozen_string_literal: true
|
4
|
+
|
5
|
+
# Copyright © 2016-2017 Exosite LLC.
|
6
|
+
# License: MIT. See LICENSE.txt.
|
7
|
+
# vim:tw=0:ts=2:sw=2:et:ai
|
8
|
+
|
9
|
+
require 'commander/import'
|
10
|
+
require 'dotenv'
|
11
|
+
require 'English'
|
12
|
+
require 'highline'
|
13
|
+
require 'pathname'
|
14
|
+
#require 'pp'
|
15
|
+
require 'rainbow'
|
16
|
+
require 'rubygems'
|
17
|
+
require 'MrMurano'
|
18
|
+
require 'MrMurano/Config'
|
19
|
+
require 'MrMurano/ProjectFile'
|
20
|
+
|
21
|
+
# DEVs: Store environs in an .env file that gets loaded here. Alternatively,
|
22
|
+
# run a Bash or similar script before you start developing.
|
23
|
+
Dotenv.load
|
24
|
+
|
25
|
+
# Don't drop traces on ^C.
|
26
|
+
# EXPLAIN/2017-06-30: [lb] not sure what "drop traces" means.
|
27
|
+
# What happens if we don't trap Ctrl-C?
|
28
|
+
# NOTE: The second parameter is either a string, or a command or block to
|
29
|
+
# call or run. Ruby honors certain special strings, like 'EXIT':
|
30
|
+
# "If the command is “EXIT”, the script will be terminated by the signal."
|
31
|
+
# Per https://ruby-doc.org/core-2.2.0/Signal.html
|
32
|
+
Signal.trap('INT', 'EXIT')
|
33
|
+
|
34
|
+
program :version, MrMurano::VERSION
|
35
|
+
|
36
|
+
program :description, %(
|
37
|
+
Manage Applications and Products in Exosite's Murano
|
38
|
+
).strip
|
39
|
+
|
40
|
+
# If being piped, e.g.,
|
41
|
+
# murano command ... | ...
|
42
|
+
# or
|
43
|
+
# VAR=$(murano command ...)
|
44
|
+
# etc., then do not do progress.
|
45
|
+
# TEST/2017-08-23: Does this work on Windows?
|
46
|
+
ARGV.push('--no-progress') unless $stdout.tty? || ARGV.include?('--no-progress')
|
47
|
+
|
48
|
+
default_command :help
|
49
|
+
|
50
|
+
# Look for plug-ins.
|
51
|
+
pgds = [
|
52
|
+
Pathname.new(Dir.home) + '.mrmurano' + 'plugins',
|
53
|
+
Pathname.new(Dir.home) + '.murano' + 'plugins',
|
54
|
+
]
|
55
|
+
# Add plugin dirs from configs
|
56
|
+
# This is run before the command line options are parsed, so need to check old way.
|
57
|
+
unless ARGV.include? '--skip-plugins'
|
58
|
+
pgds << Pathname.new(ENV['MR_MURANO_PLUGIN_DIR']) if ENV.key? 'MR_MURANO_PLUGIN_DIR'
|
59
|
+
pgds << Pathname.new(ENV['MURANO_PLUGIN_DIR']) if ENV.key? 'MURANO_PLUGIN_DIR'
|
60
|
+
pgds.each do |path|
|
61
|
+
next unless path.exist?
|
62
|
+
path.each_child do |plugin|
|
63
|
+
next if plugin.directory?
|
64
|
+
next unless plugin.readable?
|
65
|
+
next if plugin.basename.fnmatch('.*') # don't read anything starting with .
|
66
|
+
begin
|
67
|
+
require plugin.to_s
|
68
|
+
#rescue Exception => err
|
69
|
+
rescue StandardError => err
|
70
|
+
$stderr.puts "Failed to load plugin at #{plugin} because #{err}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Look for .murano/config files.
|
77
|
+
$cfg = MrMurano::Config.new(::Commander::Runner.instance)
|
78
|
+
$cfg.load
|
79
|
+
$cfg.validate_cmd
|
80
|
+
|
81
|
+
# Look for a (legacy) Solutionfile.json.
|
82
|
+
$project = MrMurano::ProjectFile.new
|
83
|
+
$project.load
|
84
|
+
|
85
|
+
# The Commander defaults to paged help.
|
86
|
+
# The user can disable with --no-page, e.g.,
|
87
|
+
# alias murano='murano --no-page'
|
88
|
+
# We define this here and not in globals.rb because
|
89
|
+
# `murano --help` does not cause globals.rb to be sourced.
|
90
|
+
paging = nil
|
91
|
+
paging = true if ARGV.include?('--page')
|
92
|
+
paging = false if ARGV.include?('--no-page')
|
93
|
+
unless paging.nil?
|
94
|
+
program :help_paging, paging
|
95
|
+
$cfg['tool.no-page'] = !paging
|
96
|
+
end
|
97
|
+
# else, commander defaults to paging.
|
98
|
+
|
data/lib/MrMurano/verbosing.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.28 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -104,7 +104,7 @@ module MrMurano
|
|
104
104
|
|
105
105
|
## Format and print the object
|
106
106
|
# Handles many of the raw 'unpolished' formats.
|
107
|
-
def outf(obj, ios=nil
|
107
|
+
def outf(obj, ios=nil)
|
108
108
|
fmt = $cfg['tool.outformat']
|
109
109
|
ios = $stdout if ios.nil?
|
110
110
|
case fmt
|
data/lib/MrMurano/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Last Modified: 2017.08.
|
1
|
+
# Last Modified: 2017.08.31 /coding: utf-8
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
# Copyright © 2016-2017 Exosite LLC.
|
@@ -26,7 +26,7 @@ module MrMurano
|
|
26
26
|
# '3.0.0-beta.2' is changed to '3.0.0.pre.beta.2'
|
27
27
|
# which breaks our build (which expects the version to match herein).
|
28
28
|
# So stick to using the '.pre.X' syntax, which ruby/gems knows.
|
29
|
-
VERSION = '3.0.
|
29
|
+
VERSION = '3.0.2'
|
30
30
|
EXE_NAME = File.basename($PROGRAM_NAME)
|
31
31
|
SIGN_UP_URL = 'https://exosite.com/signup/'
|
32
32
|
end
|