xapixctl 1.1.0 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/cd.yaml +17 -0
- data/.rubocop.yml +5 -1
- data/.ruby-version +1 -1
- data/Gemfile.lock +57 -40
- data/Rakefile +1 -1
- data/lib/xapixctl.rb +0 -3
- data/lib/xapixctl/base_cli.rb +75 -0
- data/lib/xapixctl/cli.rb +59 -159
- data/lib/xapixctl/connector_cli.rb +49 -0
- data/lib/xapixctl/phoenix_client.rb +38 -247
- data/lib/xapixctl/phoenix_client/connection.rb +50 -0
- data/lib/xapixctl/phoenix_client/organization_connection.rb +61 -0
- data/lib/xapixctl/phoenix_client/project_connection.rb +184 -0
- data/lib/xapixctl/phoenix_client/result_handler.rb +35 -0
- data/lib/xapixctl/preview_cli.rb +54 -0
- data/lib/xapixctl/sync_cli.rb +166 -0
- data/lib/xapixctl/titan_cli.rb +281 -0
- data/lib/xapixctl/util.rb +42 -0
- data/lib/xapixctl/version.rb +3 -1
- data/xapixctl.gemspec +13 -6
- metadata +67 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ba3cb0a95f481dfd6568282c75d0bc4a2db36a03c4b8a177401deac61b04eaa
|
4
|
+
data.tar.gz: f5cd613fdcb2c9a204b224b6504348c4840fe45fd3506bea904bb26d5367793a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0635abac3da2424e0109306eec1795dac8ae2cf9cb81aa4f8769ef397f5e70f4b5db7095b2820f0a49f7902d2d3e75df86b2128622fdaa10bb3082dea38ddab
|
7
|
+
data.tar.gz: f14855a202d934303acf771987686dcf395c0842a870a309283bbd080c1ebd32c0c1178e1a0df2256352c575920e4116010953a4e6d2a8833e178f27838f5e85
|
@@ -0,0 +1,17 @@
|
|
1
|
+
name: CD
|
2
|
+
on: push
|
3
|
+
jobs:
|
4
|
+
test:
|
5
|
+
runs-on: ubuntu-latest
|
6
|
+
strategy:
|
7
|
+
matrix:
|
8
|
+
ruby-version: [2.7, 2.6]
|
9
|
+
steps:
|
10
|
+
- uses: actions/checkout@v2
|
11
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
12
|
+
uses: ruby/setup-ruby@v1
|
13
|
+
with:
|
14
|
+
ruby-version: ${{ matrix.ruby-version }}
|
15
|
+
bundler-cache: true
|
16
|
+
- name: Run tests
|
17
|
+
run: bundle exec rspec
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
AllCops:
|
2
|
-
|
2
|
+
NewCops: enable
|
3
|
+
TargetRubyVersion: 2.6
|
3
4
|
DisplayCopNames: true
|
4
5
|
Exclude:
|
5
6
|
- bin/*
|
@@ -25,3 +26,6 @@ Style/OptionHash:
|
|
25
26
|
Metrics/BlockLength:
|
26
27
|
Exclude:
|
27
28
|
- spec/**/*
|
29
|
+
|
30
|
+
Naming/RescuedExceptionsVariableName:
|
31
|
+
PreferredName: 'err'
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.6.
|
1
|
+
2.6.3
|
data/Gemfile.lock
CHANGED
@@ -1,40 +1,45 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
xapixctl (1.
|
4
|
+
xapixctl (1.2.2)
|
5
5
|
activesupport (>= 5.2.3, < 6.0.0)
|
6
6
|
rest-client (>= 2.1.0, < 3.0.0)
|
7
|
-
thor (>= 0.
|
7
|
+
thor (>= 1.0.0, < 1.2.0)
|
8
8
|
|
9
9
|
GEM
|
10
10
|
remote: https://rubygems.org/
|
11
11
|
specs:
|
12
|
-
activesupport (5.2.4.
|
12
|
+
activesupport (5.2.4.5)
|
13
13
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
14
14
|
i18n (>= 0.7, < 2)
|
15
15
|
minitest (~> 5.1)
|
16
16
|
tzinfo (~> 1.1)
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
addressable (2.7.0)
|
18
|
+
public_suffix (>= 2.0.2, < 5.0)
|
19
|
+
ast (2.4.2)
|
20
|
+
concurrent-ruby (1.1.8)
|
21
|
+
crack (0.4.4)
|
22
|
+
diff-lcs (1.4.4)
|
20
23
|
domain_name (0.5.20190701)
|
21
24
|
unf (>= 0.0.5, < 1.0.0)
|
25
|
+
hashdiff (1.0.1)
|
22
26
|
http-accept (1.7.0)
|
23
27
|
http-cookie (1.0.3)
|
24
28
|
domain_name (~> 0.5)
|
25
|
-
i18n (1.8.
|
29
|
+
i18n (1.8.9)
|
26
30
|
concurrent-ruby (~> 1.0)
|
27
31
|
mime-types (3.3.1)
|
28
32
|
mime-types-data (~> 3.2015)
|
29
|
-
mime-types-data (3.
|
30
|
-
minitest (5.14.
|
33
|
+
mime-types-data (3.2021.0225)
|
34
|
+
minitest (5.14.4)
|
31
35
|
netrc (0.11.0)
|
32
|
-
parallel (1.
|
33
|
-
parser (
|
34
|
-
ast (~> 2.4.
|
36
|
+
parallel (1.20.1)
|
37
|
+
parser (3.0.0.0)
|
38
|
+
ast (~> 2.4.1)
|
39
|
+
public_suffix (4.0.6)
|
35
40
|
rainbow (3.0.0)
|
36
|
-
rake (13.0.
|
37
|
-
regexp_parser (1.
|
41
|
+
rake (13.0.3)
|
42
|
+
regexp_parser (2.1.1)
|
38
43
|
relaxed-rubocop (2.5)
|
39
44
|
rest-client (2.1.0)
|
40
45
|
http-accept (>= 1.7.0, < 2.0)
|
@@ -42,50 +47,62 @@ GEM
|
|
42
47
|
mime-types (>= 1.16, < 4.0)
|
43
48
|
netrc (~> 0.8)
|
44
49
|
rexml (3.2.4)
|
45
|
-
rspec (3.
|
46
|
-
rspec-core (~> 3.
|
47
|
-
rspec-expectations (~> 3.
|
48
|
-
rspec-mocks (~> 3.
|
49
|
-
rspec-core (3.
|
50
|
-
rspec-support (~> 3.
|
51
|
-
rspec-expectations (3.
|
50
|
+
rspec (3.10.0)
|
51
|
+
rspec-core (~> 3.10.0)
|
52
|
+
rspec-expectations (~> 3.10.0)
|
53
|
+
rspec-mocks (~> 3.10.0)
|
54
|
+
rspec-core (3.10.1)
|
55
|
+
rspec-support (~> 3.10.0)
|
56
|
+
rspec-expectations (3.10.1)
|
52
57
|
diff-lcs (>= 1.2.0, < 2.0)
|
53
|
-
rspec-support (~> 3.
|
54
|
-
rspec-mocks (3.
|
58
|
+
rspec-support (~> 3.10.0)
|
59
|
+
rspec-mocks (3.10.2)
|
55
60
|
diff-lcs (>= 1.2.0, < 2.0)
|
56
|
-
rspec-support (~> 3.
|
57
|
-
rspec-support (3.
|
58
|
-
rubocop (
|
61
|
+
rspec-support (~> 3.10.0)
|
62
|
+
rspec-support (3.10.2)
|
63
|
+
rubocop (1.11.0)
|
59
64
|
parallel (~> 1.10)
|
60
|
-
parser (>=
|
65
|
+
parser (>= 3.0.0.0)
|
61
66
|
rainbow (>= 2.2.2, < 4.0)
|
62
|
-
regexp_parser (>= 1.
|
67
|
+
regexp_parser (>= 1.8, < 3.0)
|
63
68
|
rexml
|
64
|
-
rubocop-ast (>= 0.0
|
69
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
65
70
|
ruby-progressbar (~> 1.7)
|
66
|
-
unicode-display_width (>= 1.4.0, <
|
67
|
-
rubocop-ast (
|
68
|
-
parser (>= 2.7.
|
69
|
-
|
70
|
-
|
71
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
72
|
+
rubocop-ast (1.4.1)
|
73
|
+
parser (>= 2.7.1.5)
|
74
|
+
rubocop-rake (0.5.1)
|
75
|
+
rubocop
|
76
|
+
rubocop-rspec (2.2.0)
|
77
|
+
rubocop (~> 1.0)
|
78
|
+
rubocop-ast (>= 1.1.0)
|
79
|
+
ruby-progressbar (1.11.0)
|
80
|
+
thor (1.1.0)
|
71
81
|
thread_safe (0.3.6)
|
72
|
-
tzinfo (1.2.
|
82
|
+
tzinfo (1.2.9)
|
73
83
|
thread_safe (~> 0.1)
|
74
84
|
unf (0.1.4)
|
75
85
|
unf_ext
|
76
86
|
unf_ext (0.0.7.7)
|
77
|
-
unicode-display_width (
|
87
|
+
unicode-display_width (2.0.0)
|
88
|
+
webmock (3.11.0)
|
89
|
+
addressable (>= 2.3.6)
|
90
|
+
crack (>= 0.3.2)
|
91
|
+
hashdiff (>= 0.4.0, < 2.0.0)
|
78
92
|
|
79
93
|
PLATFORMS
|
80
94
|
ruby
|
81
95
|
|
82
96
|
DEPENDENCIES
|
83
|
-
bundler (~> 1.
|
97
|
+
bundler (~> 2.1.4)
|
84
98
|
rake (~> 13.0)
|
85
99
|
relaxed-rubocop (~> 2.5)
|
86
|
-
rspec (~> 3.0)
|
87
|
-
rubocop (~>
|
100
|
+
rspec (~> 3.10.0)
|
101
|
+
rubocop (~> 1.11.0)
|
102
|
+
rubocop-rake (~> 0.5.1)
|
103
|
+
rubocop-rspec (~> 2.2.0)
|
104
|
+
webmock (~> 3.11.0)
|
88
105
|
xapixctl!
|
89
106
|
|
90
107
|
BUNDLED WITH
|
91
|
-
1.
|
108
|
+
2.1.4
|
data/Rakefile
CHANGED
data/lib/xapixctl.rb
CHANGED
@@ -4,9 +4,6 @@ require 'active_support'
|
|
4
4
|
require 'active_support/core_ext/hash/keys'
|
5
5
|
require 'active_support/core_ext/object/blank'
|
6
6
|
require 'active_support/core_ext/string/inflections'
|
7
|
-
require 'rest_client'
|
8
|
-
require 'json'
|
9
|
-
require 'psych'
|
10
7
|
require 'xapixctl/version'
|
11
8
|
require 'xapixctl/phoenix_client'
|
12
9
|
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'thor'
|
4
|
+
require 'xapixctl/util'
|
5
|
+
|
6
|
+
module Xapixctl
|
7
|
+
class BaseCli < Thor
|
8
|
+
def self.exit_on_failure?; true; end
|
9
|
+
|
10
|
+
def self.start(given_args = ARGV, config = {})
|
11
|
+
super
|
12
|
+
rescue StandardError => err
|
13
|
+
config[:debug] || ENV["THOR_DEBUG"] == "1" ? (raise err) : config[:shell].error(err.message)
|
14
|
+
exit(false) if exit_on_failure?
|
15
|
+
end
|
16
|
+
|
17
|
+
class_option :org, aliases: "-o", desc: "Organization; Fallback: environment variable XAPIX_ORG"
|
18
|
+
class_option :project, aliases: "-p", desc: "Project, can be ORG/PROJECT; Fallback: environment variable XAPIX_PROJECT"
|
19
|
+
class_option :debug, type: :boolean, desc: "Print details for debugging"
|
20
|
+
class_option :xapix_url, desc: "Fallback: environment variable XAPIX_URL. URL to Xapix. Default: https://cloud.xapix.io/"
|
21
|
+
class_option :xapix_token, desc: "Fallback: environment variable XAPIX_TOKEN. Your access token."
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def exit_with_api_error(err, result)
|
26
|
+
details = result['errors'].map { |k| k['detail'] }.unshift('').join("\n ") rescue err.to_s
|
27
|
+
warn "API error: #{details}"
|
28
|
+
exit 1
|
29
|
+
end
|
30
|
+
|
31
|
+
def show_deployment_status(result)
|
32
|
+
return unless result && result['project_publication']
|
33
|
+
puts "deployment: #{result.dig('project_publication', 'deployment')}"
|
34
|
+
puts " data api: #{result.dig('project_publication', 'data_api')} (version: #{result.dig('project_publication', 'data_api_version').presence || 'n/a'})"
|
35
|
+
puts " user management: #{result.dig('project_publication', 'user_management')}"
|
36
|
+
if result.dig('project_publication', 'deployment') == 'success'
|
37
|
+
puts " base URL: #{result.dig('project_publication', 'base_url')}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def connection
|
42
|
+
@connection ||= begin
|
43
|
+
url = options[:xapix_url] || ENV['XAPIX_URL'] || 'https://cloud.xapix.io/'
|
44
|
+
token = options[:xapix_token] || ENV['XAPIX_TOKEN']
|
45
|
+
raise Thor::RequiredArgumentMissingError, "No XAPIX_TOKEN given. Either use --xapix_token [TOKEN] or set environment variable XAPIX_TOKEN (recommended)" if !token
|
46
|
+
PhoenixClient.connection(
|
47
|
+
url, token,
|
48
|
+
default_error_handler: ->(err, result) { exit_with_api_error(err, result) },
|
49
|
+
logging: options[:debug] ? 'stdout' : nil
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def org_or_prj_connection
|
55
|
+
options[:project] ? prj_connection : org_connection
|
56
|
+
end
|
57
|
+
|
58
|
+
def org_connection
|
59
|
+
org = options[:org] || ENV['XAPIX_ORG']
|
60
|
+
raise Thor::RequiredArgumentMissingError, "No organization given. Either use --org [ORG] or set environment variable XAPIX_ORG" if !org
|
61
|
+
@org_connection ||= connection.organization(org)
|
62
|
+
end
|
63
|
+
|
64
|
+
def prj_connection
|
65
|
+
project = options[:project] || ENV['XAPIX_PROJECT']
|
66
|
+
org = options[:org] || ENV['XAPIX_ORG']
|
67
|
+
raise Thor::RequiredArgumentMissingError, "No project given. Either use --project [ORG/PROJECT] or set environment variable XAPIX_PROJECT" if !project
|
68
|
+
if project.include?('/')
|
69
|
+
org, project = project.split('/', 2)
|
70
|
+
end
|
71
|
+
raise Thor::RequiredArgumentMissingError, "No organization given. Either use --org [ORG] or set environment variable XAPIX_ORG" if !org
|
72
|
+
@prj_connection ||= connection.project(org: org, project: project)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/xapixctl/cli.rb
CHANGED
@@ -1,27 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'xapixctl/base_cli'
|
4
|
+
require 'xapixctl/connector_cli'
|
5
|
+
require 'xapixctl/preview_cli'
|
6
|
+
require 'xapixctl/sync_cli'
|
7
|
+
require 'xapixctl/titan_cli'
|
4
8
|
|
5
9
|
module Xapixctl
|
6
|
-
class Cli <
|
7
|
-
|
10
|
+
class Cli < BaseCli
|
11
|
+
desc "connectors SUBCOMMAND ...ARGS", "Commands for Connector resources"
|
12
|
+
subcommand "connectors", ConnectorCli
|
8
13
|
|
9
|
-
|
10
|
-
|
11
|
-
|
14
|
+
desc "preview SUBCOMMAND ...ARGS", "Request preview for resources"
|
15
|
+
subcommand "preview", PreviewCli
|
16
|
+
|
17
|
+
desc "sync SUBCOMMAND ...ARGS", "Sync resources"
|
18
|
+
subcommand "sync", SyncCli
|
19
|
+
|
20
|
+
desc "titan SUBCOMMAND ...ARGS", "Tools for ML model deployments and service generation", hide: true
|
21
|
+
subcommand "titan", TitanCli
|
12
22
|
|
13
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
14
|
-
option :project, aliases: "-p", desc: "Project"
|
15
23
|
option :format, aliases: "-f", default: 'text', enum: ['text', 'yaml', 'json'], desc: "Output format"
|
16
24
|
desc "get TYPE [ID]", "retrieve either all resources of given TYPE or just the resource of given TYPE and ID"
|
17
25
|
long_desc <<-LONGDESC
|
18
26
|
`xapixctl get TYPE` will retrieve the list of all resources of given type.
|
19
27
|
|
20
28
|
If requested on an organization (i.e. no project given), the following types are available:
|
21
|
-
\
|
29
|
+
\x5Project
|
22
30
|
|
23
31
|
If requested on an a project (i.e. organization and project are given), the following types are available:
|
24
|
-
\x5
|
32
|
+
\x5#{PhoenixClient::SUPPORTED_RESOURCE_TYPES.sort.join(', ')}
|
25
33
|
|
26
34
|
Use the format to switch between the different output formats.
|
27
35
|
|
@@ -29,31 +37,17 @@ module Xapixctl
|
|
29
37
|
\x5> $ xapixctl get -o xapix Project
|
30
38
|
\x5> $ xapixctl get -o xapix Project some-project
|
31
39
|
\x5> $ xapixctl get -o xapix -p some-project DataSource
|
32
|
-
\x5> $ xapixctl get -
|
40
|
+
\x5> $ xapixctl get -p xapix/some-project DataSource
|
41
|
+
\x5> $ xapixctl get -p xapix/some-project DataSource get-a-list
|
33
42
|
LONGDESC
|
34
43
|
def get(resource_type, resource_id = nil)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
else
|
41
|
-
connection.resource_ids(resource_type, org: options[:org], project: options[:project]) do |res|
|
42
|
-
res.on_success do |resource_ids|
|
43
|
-
resource_ids.each do |resource_id|
|
44
|
-
connection.resource(resource_type, resource_id, org: options[:org], project: options[:project], format: options[:format].to_sym) do |res|
|
45
|
-
res.on_success { |resource| puts resource }
|
46
|
-
res.on_error { |err, result| warn_api_error("could not get", err, result) }
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
res.on_error { |err, result| warn_api_error("could not get", err, result) }
|
51
|
-
end
|
44
|
+
conn = org_or_prj_connection
|
45
|
+
resource_ids = resource_id ? [resource_id] : conn.resource_ids(resource_type)
|
46
|
+
resource_ids.each do |res_id|
|
47
|
+
puts conn.resource(resource_type, res_id, format: options[:format].to_sym)
|
52
48
|
end
|
53
49
|
end
|
54
50
|
|
55
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
56
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
57
51
|
option :format, aliases: "-f", default: 'text', enum: ['text', 'yaml', 'json'], desc: "Output format"
|
58
52
|
desc "export", "retrieves all resources within a project"
|
59
53
|
long_desc <<-LONGDESC
|
@@ -63,19 +57,15 @@ module Xapixctl
|
|
63
57
|
|
64
58
|
Examples:
|
65
59
|
\x5> $ xapixctl export -o xapix -p some-project
|
66
|
-
\x5> $ xapixctl export -
|
60
|
+
\x5> $ xapixctl export -p xapix/some-project
|
61
|
+
\x5> $ xapixctl export -p xapix/some-project -f yaml > some_project.yaml
|
67
62
|
LONGDESC
|
68
63
|
def export
|
69
|
-
|
70
|
-
|
71
|
-
res.on_error { |err, result| warn_api_error("could not get", err, result) }
|
72
|
-
end
|
73
|
-
(connection.resource_types_for_export - ['Project']).each { |type| get(type) }
|
64
|
+
get('Project', prj_connection.project)
|
65
|
+
prj_connection.resource_types_for_export.each { |type| get(type) }
|
74
66
|
end
|
75
67
|
|
76
|
-
option :
|
77
|
-
option :project, aliases: "-p", desc: "Project"
|
78
|
-
option :file, aliases: "-f", required: true
|
68
|
+
option :file, aliases: "-f", required: true, desc: 'file or directory from which to load resource descriptions'
|
79
69
|
desc "apply", "Create or update a resource from a file"
|
80
70
|
long_desc <<-LONGDESC
|
81
71
|
`xapixctl apply -f FILE` will apply the given resource description.
|
@@ -85,120 +75,72 @@ module Xapixctl
|
|
85
75
|
If applied on a project (i.e. organization and project are given), the given project is used.
|
86
76
|
|
87
77
|
The given file should be in YAML format and can contain multiple resource definitions, each as it's own YAML document.
|
78
|
+
You can also provide a directory, in which case all files with yml/yaml extension will get loaded.
|
88
79
|
You can also read from stdin by using '-'.
|
89
80
|
|
90
81
|
Examples:
|
91
82
|
\x5> $ xapixctl apply -o xapix -f get_a_list.yaml
|
92
83
|
\x5> $ xapixctl apply -o xapix -p some-project -f get_a_list.yaml
|
84
|
+
\x5> $ xapixctl apply -p xapix/some-project -f get_a_list.yaml
|
85
|
+
\x5> $ xapixctl apply -p xapix/some-project -f ./
|
93
86
|
|
94
87
|
To copy over all data sources from one project to another:
|
95
88
|
\x5> $ xapixctl get -o xapix-old -p some-project DataSource -f yaml | xapixctl apply -o xapix-new -f -
|
96
89
|
LONGDESC
|
97
90
|
def apply
|
98
|
-
resources_from_file(options[:file]) do |desc|
|
91
|
+
Util.resources_from_file(options[:file]) do |desc|
|
99
92
|
puts "applying #{desc['kind']} #{desc.dig('metadata', 'id')}"
|
100
|
-
|
101
|
-
res.on_success { puts 'OK' }
|
102
|
-
res.on_error { |err, result| warn_api_error("could not apply changes", err, result); break }
|
103
|
-
end
|
93
|
+
org_or_prj_connection.apply(desc)
|
104
94
|
end
|
105
95
|
end
|
106
96
|
|
107
|
-
option :
|
108
|
-
option :project, aliases: "-p", desc: "Project"
|
109
|
-
option :file, aliases: "-f"
|
97
|
+
option :file, aliases: "-f", desc: 'file or directory from which to load resource descriptions'
|
110
98
|
desc "delete [TYPE ID] [-f FILE]", "delete the resources in the file"
|
111
99
|
long_desc <<-LONGDESC
|
112
100
|
`xapixctl delete -f FILE` will delete all the resources listed in the file.
|
113
101
|
\x5`xapixctl delete TYPE ID` will delete the resource by given TYPE and ID.
|
114
102
|
|
115
103
|
The given file should be in YAML format and can contain multiple resource definitions, each as it's own YAML document.
|
104
|
+
You can also provide a directory, in which case all files with yml/yaml extension will get loaded.
|
116
105
|
You can also read from stdin by using '-'.
|
117
106
|
|
118
107
|
Examples:
|
119
|
-
\x5> $ xapixctl delete -o xapix -p some-project -f get_a_list.yaml
|
120
|
-
\x5> $ xapixctl delete -o xapix -p some-project DataSource get-a-list
|
121
108
|
\x5> $ xapixctl delete -o xapix Project some-project
|
109
|
+
\x5> $ xapixctl delete -p xapix -p some-project DataSource get-a-list
|
110
|
+
\x5> $ xapixctl delete -p xapix/some-project DataSource get-a-list
|
111
|
+
\x5> $ xapixctl delete -p xapix/some-project -f get_a_list.yaml
|
112
|
+
\x5> $ xapixctl delete -p xapix/some-project -f ./
|
122
113
|
LONGDESC
|
123
114
|
def delete(resource_type = nil, resource_id = nil)
|
124
115
|
if resource_type && resource_id
|
125
|
-
|
126
|
-
|
127
|
-
res.on_error { |err, result| warn_api_error("could not delete", err, result) }
|
128
|
-
end
|
116
|
+
org_or_prj_connection.delete(resource_type, resource_id)
|
117
|
+
puts "DELETED #{resource_type} #{resource_id}"
|
129
118
|
elsif options[:file]
|
130
|
-
resources_from_file(options[:file]) do |desc|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
connection.delete(type, id, org: options[:org], project: options[:project]) do |res|
|
135
|
-
res.on_success { puts "DELETED #{type} #{id}" }
|
136
|
-
res.on_error { |err, result| warn_api_error("could not delete", err, result); break }
|
137
|
-
end
|
119
|
+
Util.resources_from_file(options[:file]) do |desc|
|
120
|
+
res_type = desc['kind']
|
121
|
+
res_id = desc.dig('metadata', 'id')
|
122
|
+
delete(res_type, res_id)
|
138
123
|
end
|
139
124
|
else
|
140
125
|
warn "need TYPE and ID or --file option"
|
141
126
|
end
|
142
127
|
end
|
143
128
|
|
144
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
145
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
146
|
-
option :format, aliases: "-f", default: 'text', enum: ['text', 'yaml', 'json'], desc: "Output format"
|
147
|
-
desc "preview ID", "Preview a pipeline"
|
148
|
-
long_desc <<-LONGDESC
|
149
|
-
`xapixctl preview` will return a preview of the given pipeline.
|
150
|
-
|
151
|
-
The preview function will not call any external data sources but calculate a preview based on the provided sample data.
|
152
|
-
|
153
|
-
To preview a pipeline attached to an endpoint, please use `xapixctl preview-ep` to see the correct preview.
|
154
|
-
|
155
|
-
Examples:
|
156
|
-
\x5> $ xapixctl preview -o xapix -p some-project pipeline
|
157
|
-
LONGDESC
|
158
|
-
def preview(pipeline)
|
159
|
-
connection.pipeline_preview(pipeline, org: options[:org], project: options[:project], format: options[:format].to_sym) do |res|
|
160
|
-
res.on_success { |preview| puts preview }
|
161
|
-
res.on_error { |err, result| warn_api_error('could not fetch preview', err, result) }
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
166
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
167
|
-
option :format, aliases: "-f", default: 'text', enum: ['text', 'yaml', 'json'], desc: "Output format"
|
168
|
-
desc "preview-ep ID", "Preview an endpoint"
|
169
|
-
long_desc <<-LONGDESC
|
170
|
-
`xapixctl preview-ep` will return a preview of the given endpoint.
|
171
|
-
|
172
|
-
The preview function will not call any external data sources but calculate a preview based on the provided sample data.
|
173
|
-
|
174
|
-
Examples:
|
175
|
-
\x5> $ xapixctl preview-ep -o xapix -p some-project endpoint
|
176
|
-
LONGDESC
|
177
|
-
def preview_ep(endpoint)
|
178
|
-
connection.endpoint_preview(endpoint, org: options[:org], project: options[:project], format: options[:format].to_sym) do |res|
|
179
|
-
res.on_success { |preview| puts preview }
|
180
|
-
res.on_error { |err, result| warn_api_error('could not fetch preview', err, result) }
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
185
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
186
129
|
desc "publish", "Publishes the current version of the given project"
|
187
130
|
long_desc <<-LONGDESC
|
188
131
|
`xapixctl publish` will publish the given project.
|
189
132
|
|
190
133
|
Examples:
|
191
134
|
\x5> $ xapixctl publish -o xapix -p some-project
|
135
|
+
\x5> $ xapixctl publish -p xapix/some-project
|
192
136
|
LONGDESC
|
193
137
|
def publish
|
194
|
-
|
138
|
+
prj_connection.publish do |res|
|
195
139
|
res.on_success { |result| show_deployment_status(result) }
|
196
|
-
res.on_error { |err, result| show_deployment_status(result);
|
140
|
+
res.on_error { |err, result| show_deployment_status(result); exit_with_api_error(err, result) }
|
197
141
|
end
|
198
142
|
end
|
199
143
|
|
200
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
201
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
202
144
|
desc "logs CORRELATION_ID", "Retrieves the execution logs for the given correlation ID"
|
203
145
|
long_desc <<-LONGDESC
|
204
146
|
`xapixctl logs CORRELATION_ID` will retrieve execution logs for the given correlation ID.
|
@@ -207,66 +149,24 @@ module Xapixctl
|
|
207
149
|
|
208
150
|
Examples:
|
209
151
|
\x5> $ xapixctl logs be9c8608-e291-460d-bc20-5a394c4079d4 -o xapix -p some-project
|
152
|
+
\x5> $ xapixctl logs be9c8608-e291-460d-bc20-5a394c4079d4 -p xapix/some-project
|
210
153
|
LONGDESC
|
211
154
|
def logs(correlation_id)
|
212
|
-
|
213
|
-
|
214
|
-
res.on_error { |err, result| warn_api_error('could not get logs', err, result) }
|
215
|
-
end
|
155
|
+
result = prj_connection.logs(correlation_id)
|
156
|
+
puts result['logs'].to_yaml
|
216
157
|
end
|
217
158
|
|
218
159
|
SUPPORTED_CONTEXTS = ['Project', 'Organization'].freeze
|
160
|
+
|
219
161
|
desc "api-resources", "retrieves a list of all available resource types"
|
220
162
|
def api_resources
|
221
|
-
connection.available_resource_types
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
puts format_str % [desc['type'], desc['context']]
|
228
|
-
end
|
229
|
-
end
|
230
|
-
res.on_error { |err, result| warn_api_error("could not get", err, result) }
|
163
|
+
available_types = connection.available_resource_types
|
164
|
+
format_str = "%20.20s %20.20s %26.26s"
|
165
|
+
puts format_str % ['Type', 'Required Context', '']
|
166
|
+
available_types.sort_by { |desc| desc['type'] }.each do |desc|
|
167
|
+
next unless SUPPORTED_CONTEXTS.include?(desc['context'])
|
168
|
+
puts format_str % [desc['type'], desc['context'], PhoenixClient.supported_type?(desc['type']) ? '' : '(unsupported, update CLI)']
|
231
169
|
end
|
232
170
|
end
|
233
|
-
|
234
|
-
private
|
235
|
-
|
236
|
-
def warn_api_error(text, err, result)
|
237
|
-
details = "\n " + result['errors'].map { |k| k['detail'] }.join("\n ") rescue err.to_s
|
238
|
-
warn "#{text}: #{details}"
|
239
|
-
exit 1
|
240
|
-
end
|
241
|
-
|
242
|
-
def show_deployment_status(result)
|
243
|
-
return unless result && result['project_publication']
|
244
|
-
puts "deployment: #{result.dig('project_publication', 'deployment')}"
|
245
|
-
puts " data api: #{result.dig('project_publication', 'data_api')} (version: #{result.dig('project_publication', 'data_api_version').presence || 'n/a'})"
|
246
|
-
puts " user management: #{result.dig('project_publication', 'user_management')}"
|
247
|
-
if result.dig('project_publication', 'deployment') == 'success'
|
248
|
-
puts " base URL: #{result.dig('project_publication', 'base_url')}"
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
DOCUMENT_STRUCTURE = %w[version kind metadata definition].freeze
|
253
|
-
def resources_from_file(filename)
|
254
|
-
yaml_string = filename == '-' ? $stdin.read : IO.read(filename)
|
255
|
-
yaml_string.split(/^---\s*\n/).map { |yml| Psych.safe_load(yml) }.compact.each do |doc|
|
256
|
-
unless (DOCUMENT_STRUCTURE - doc.keys.map(&:to_s)).empty?
|
257
|
-
warn "does not look like a correct resource definition:"
|
258
|
-
warn doc.inspect
|
259
|
-
exit 1
|
260
|
-
end
|
261
|
-
yield doc
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
def connection
|
266
|
-
url = options[:xapix_url] || ENV['XAPIX_URL'] || 'https://cloud.xapix.io/'
|
267
|
-
token = options[:xapix_token] || ENV['XAPIX_TOKEN']
|
268
|
-
raise Thor::RequiredArgumentMissingError, "no XAPIX_TOKEN given. Either use --xapix_token [TOKEN] or set environment variable XAPIX_TOKEN (recommended)" if !token
|
269
|
-
PhoenixClient::Connection.new(url, token)
|
270
|
-
end
|
271
171
|
end
|
272
172
|
end
|