xapixctl 1.0.0 → 1.2.1
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/.github/workflows/cd.yaml +17 -0
- data/.rubocop.yml +5 -1
- data/.ruby-version +1 -1
- data/Gemfile.lock +63 -41
- data/README.md +8 -0
- data/Rakefile +1 -1
- data/lib/xapixctl.rb +0 -3
- data/lib/xapixctl/base_cli.rb +75 -0
- data/lib/xapixctl/cli.rb +68 -136
- data/lib/xapixctl/phoenix_client.rb +58 -142
- 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 +164 -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/util.rb +42 -0
- data/lib/xapixctl/version.rb +3 -1
- data/xapixctl.gemspec +16 -9
- metadata +93 -24
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 175a3c54493e14738757b5eb95ef1da9724b961f460d1ac5dfb17ea6eb696507
|
4
|
+
data.tar.gz: 0a79951ab81a2b69d0087161191097cf24b01e2282887d03b12e8f32527d3707
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 040c017fb340670f8751a45c5b9c0c659cd814bb712cc74fb40e368f714fb1b80759d9c4387cbbb19999cfd512fc389a082168cde33f67cc1fd9fa0fb17b42f3
|
7
|
+
data.tar.gz: 1bdbbbb3da472ade7b520cfebc284ebebdeb871ee77c3bafa5fb22789bf4c0057d4dc7ff116ee3c0d611dbd692d99a96ac168ffa8824be006b22b124c7e98bf7
|
@@ -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,86 +1,108 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
xapixctl (1.
|
5
|
-
activesupport (
|
6
|
-
rest-client (
|
7
|
-
thor (
|
4
|
+
xapixctl (1.2.1)
|
5
|
+
activesupport (>= 5.2.3, < 6.0.0)
|
6
|
+
rest-client (>= 2.1.0, < 3.0.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
|
-
jaro_winkler (1.5.4)
|
28
31
|
mime-types (3.3.1)
|
29
32
|
mime-types-data (~> 3.2015)
|
30
|
-
mime-types-data (3.
|
31
|
-
minitest (5.14.
|
33
|
+
mime-types-data (3.2021.0225)
|
34
|
+
minitest (5.14.4)
|
32
35
|
netrc (0.11.0)
|
33
|
-
parallel (1.
|
34
|
-
parser (
|
35
|
-
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)
|
36
40
|
rainbow (3.0.0)
|
37
|
-
rake (
|
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)
|
41
46
|
http-cookie (>= 1.0.2, < 2.0)
|
42
47
|
mime-types (>= 1.16, < 4.0)
|
43
48
|
netrc (~> 0.8)
|
44
|
-
|
45
|
-
|
46
|
-
rspec-
|
47
|
-
rspec-
|
48
|
-
|
49
|
-
|
50
|
-
|
49
|
+
rexml (3.2.4)
|
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)
|
51
57
|
diff-lcs (>= 1.2.0, < 2.0)
|
52
|
-
rspec-support (~> 3.
|
53
|
-
rspec-mocks (3.
|
58
|
+
rspec-support (~> 3.10.0)
|
59
|
+
rspec-mocks (3.10.2)
|
54
60
|
diff-lcs (>= 1.2.0, < 2.0)
|
55
|
-
rspec-support (~> 3.
|
56
|
-
rspec-support (3.
|
57
|
-
rubocop (
|
58
|
-
jaro_winkler (~> 1.5.1)
|
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)
|
67
|
+
regexp_parser (>= 1.8, < 3.0)
|
68
|
+
rexml
|
69
|
+
rubocop-ast (>= 1.2.0, < 2.0)
|
62
70
|
ruby-progressbar (~> 1.7)
|
63
|
-
unicode-display_width (>= 1.4.0, <
|
64
|
-
|
65
|
-
|
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)
|
66
81
|
thread_safe (0.3.6)
|
67
|
-
tzinfo (1.2.
|
82
|
+
tzinfo (1.2.9)
|
68
83
|
thread_safe (~> 0.1)
|
69
84
|
unf (0.1.4)
|
70
85
|
unf_ext
|
71
|
-
unf_ext (0.0.7.
|
72
|
-
unicode-display_width (
|
86
|
+
unf_ext (0.0.7.7)
|
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)
|
73
92
|
|
74
93
|
PLATFORMS
|
75
94
|
ruby
|
76
95
|
|
77
96
|
DEPENDENCIES
|
78
|
-
bundler (~> 1.
|
79
|
-
rake (~>
|
97
|
+
bundler (~> 2.1.4)
|
98
|
+
rake (~> 13.0)
|
80
99
|
relaxed-rubocop (~> 2.5)
|
81
|
-
rspec (~> 3.0)
|
82
|
-
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)
|
83
105
|
xapixctl!
|
84
106
|
|
85
107
|
BUNDLED WITH
|
86
|
-
1.
|
108
|
+
2.1.4
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# xapixctl
|
2
2
|
|
3
|
+
[](https://badge.fury.io/rb/xapixctl)
|
4
|
+
|
3
5
|
Xapix client library and command line tool
|
4
6
|
|
5
7
|
## Installation
|
@@ -8,6 +10,12 @@ Install it via:
|
|
8
10
|
|
9
11
|
$ gem install xapixctl
|
10
12
|
|
13
|
+
On Windows make sure you have ruby installed:
|
14
|
+
|
15
|
+
$ choco install ruby -y
|
16
|
+
$ refreshenv
|
17
|
+
$ gem install xapixctl
|
18
|
+
|
11
19
|
## Usage
|
12
20
|
|
13
21
|
To see more details on how to run xapixctl, use:
|
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,232 +1,164 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'xapixctl/base_cli'
|
4
|
+
require 'xapixctl/preview_cli'
|
5
|
+
require 'xapixctl/sync_cli'
|
4
6
|
|
5
7
|
module Xapixctl
|
6
|
-
class Cli <
|
7
|
-
|
8
|
+
class Cli < BaseCli
|
9
|
+
desc "preview SUBCOMMAND ...ARGS", "Request preview for resources"
|
10
|
+
subcommand "preview", PreviewCli
|
8
11
|
|
9
|
-
|
10
|
-
|
11
|
-
class_option :xapix_token, desc: "Fallback: environment variable XAPIX_TOKEN. Your access token."
|
12
|
+
desc "sync SUBCOMMAND ...ARGS", "Sync resources"
|
13
|
+
subcommand "sync", SyncCli
|
12
14
|
|
13
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
14
|
-
option :project, aliases: "-p", desc: "Project"
|
15
15
|
option :format, aliases: "-f", default: 'text', enum: ['text', 'yaml', 'json'], desc: "Output format"
|
16
16
|
desc "get TYPE [ID]", "retrieve either all resources of given TYPE or just the resource of given TYPE and ID"
|
17
17
|
long_desc <<-LONGDESC
|
18
|
-
`
|
18
|
+
`xapixctl get TYPE` will retrieve the list of all resources of given type.
|
19
19
|
|
20
20
|
If requested on an organization (i.e. no project given), the following types are available:
|
21
|
-
\
|
21
|
+
\x5Project
|
22
22
|
|
23
23
|
If requested on an a project (i.e. organization and project are given), the following types are available:
|
24
|
-
\x5
|
24
|
+
\x5#{PhoenixClient::SUPPORTED_RESOURCE_TYPES.sort.join(', ')}
|
25
25
|
|
26
26
|
Use the format to switch between the different output formats.
|
27
27
|
|
28
28
|
Examples:
|
29
|
-
\x5> $
|
30
|
-
\x5> $
|
31
|
-
\x5> $
|
32
|
-
\x5> $
|
29
|
+
\x5> $ xapixctl get -o xapix Project
|
30
|
+
\x5> $ xapixctl get -o xapix Project some-project
|
31
|
+
\x5> $ xapixctl get -o xapix -p some-project DataSource
|
32
|
+
\x5> $ xapixctl get -p xapix/some-project DataSource
|
33
|
+
\x5> $ xapixctl get -p xapix/some-project DataSource get-a-list
|
33
34
|
LONGDESC
|
34
35
|
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
|
36
|
+
conn = org_or_prj_connection
|
37
|
+
resource_ids = resource_id ? [resource_id] : conn.resource_ids(resource_type)
|
38
|
+
resource_ids.each do |res_id|
|
39
|
+
puts conn.resource(resource_type, res_id, format: options[:format].to_sym)
|
52
40
|
end
|
53
41
|
end
|
54
42
|
|
55
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
56
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
57
43
|
option :format, aliases: "-f", default: 'text', enum: ['text', 'yaml', 'json'], desc: "Output format"
|
58
44
|
desc "export", "retrieves all resources within a project"
|
59
45
|
long_desc <<-LONGDESC
|
60
|
-
`
|
46
|
+
`xapixctl export` will retrieve the list of all resources of given type.
|
61
47
|
|
62
48
|
Use the format to switch between the different output formats.
|
63
49
|
|
64
50
|
Examples:
|
65
|
-
\x5> $
|
66
|
-
\x5> $
|
51
|
+
\x5> $ xapixctl export -o xapix -p some-project
|
52
|
+
\x5> $ xapixctl export -p xapix/some-project
|
53
|
+
\x5> $ xapixctl export -p xapix/some-project -f yaml > some_project.yaml
|
67
54
|
LONGDESC
|
68
55
|
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) }
|
56
|
+
get('Project', prj_connection.project)
|
57
|
+
prj_connection.resource_types_for_export.each { |type| get(type) }
|
74
58
|
end
|
75
59
|
|
76
|
-
option :
|
77
|
-
option :project, aliases: "-p", desc: "Project"
|
78
|
-
option :file, aliases: "-f", required: true
|
60
|
+
option :file, aliases: "-f", required: true, desc: 'file or directory from which to load resource descriptions'
|
79
61
|
desc "apply", "Create or update a resource from a file"
|
80
62
|
long_desc <<-LONGDESC
|
81
|
-
`
|
63
|
+
`xapixctl apply -f FILE` will apply the given resource description.
|
82
64
|
|
83
65
|
If applied on an organization (i.e. no project given), the project is taken from the resource description.
|
84
66
|
|
85
67
|
If applied on a project (i.e. organization and project are given), the given project is used.
|
86
68
|
|
87
69
|
The given file should be in YAML format and can contain multiple resource definitions, each as it's own YAML document.
|
70
|
+
You can also provide a directory, in which case all files with yml/yaml extension will get loaded.
|
88
71
|
You can also read from stdin by using '-'.
|
89
72
|
|
90
73
|
Examples:
|
91
|
-
\x5> $
|
92
|
-
\x5> $
|
74
|
+
\x5> $ xapixctl apply -o xapix -f get_a_list.yaml
|
75
|
+
\x5> $ xapixctl apply -o xapix -p some-project -f get_a_list.yaml
|
76
|
+
\x5> $ xapixctl apply -p xapix/some-project -f get_a_list.yaml
|
77
|
+
\x5> $ xapixctl apply -p xapix/some-project -f ./
|
93
78
|
|
94
79
|
To copy over all data sources from one project to another:
|
95
|
-
\x5> $
|
80
|
+
\x5> $ xapixctl get -o xapix-old -p some-project DataSource -f yaml | xapixctl apply -o xapix-new -f -
|
96
81
|
LONGDESC
|
97
82
|
def apply
|
98
|
-
resources_from_file(options[:file]) do |desc|
|
83
|
+
Util.resources_from_file(options[:file]) do |desc|
|
99
84
|
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
|
85
|
+
org_or_prj_connection.apply(desc)
|
104
86
|
end
|
105
87
|
end
|
106
88
|
|
107
|
-
option :
|
108
|
-
option :project, aliases: "-p", desc: "Project"
|
109
|
-
option :file, aliases: "-f"
|
89
|
+
option :file, aliases: "-f", desc: 'file or directory from which to load resource descriptions'
|
110
90
|
desc "delete [TYPE ID] [-f FILE]", "delete the resources in the file"
|
111
91
|
long_desc <<-LONGDESC
|
112
|
-
`
|
113
|
-
\x5`
|
92
|
+
`xapixctl delete -f FILE` will delete all the resources listed in the file.
|
93
|
+
\x5`xapixctl delete TYPE ID` will delete the resource by given TYPE and ID.
|
114
94
|
|
115
95
|
The given file should be in YAML format and can contain multiple resource definitions, each as it's own YAML document.
|
96
|
+
You can also provide a directory, in which case all files with yml/yaml extension will get loaded.
|
116
97
|
You can also read from stdin by using '-'.
|
117
98
|
|
118
99
|
Examples:
|
119
|
-
\x5> $
|
120
|
-
\x5> $
|
121
|
-
\x5> $
|
100
|
+
\x5> $ xapixctl delete -o xapix Project some-project
|
101
|
+
\x5> $ xapixctl delete -p xapix -p some-project DataSource get-a-list
|
102
|
+
\x5> $ xapixctl delete -p xapix/some-project DataSource get-a-list
|
103
|
+
\x5> $ xapixctl delete -p xapix/some-project -f get_a_list.yaml
|
104
|
+
\x5> $ xapixctl delete -p xapix/some-project -f ./
|
122
105
|
LONGDESC
|
123
106
|
def delete(resource_type = nil, resource_id = nil)
|
124
107
|
if resource_type && resource_id
|
125
|
-
|
126
|
-
|
127
|
-
res.on_error { |err, result| warn_api_error("could not delete", err, result) }
|
128
|
-
end
|
108
|
+
org_or_prj_connection.delete(resource_type, resource_id)
|
109
|
+
puts "DELETED #{resource_type} #{resource_id}"
|
129
110
|
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
|
111
|
+
Util.resources_from_file(options[:file]) do |desc|
|
112
|
+
res_type = desc['kind']
|
113
|
+
res_id = desc.dig('metadata', 'id')
|
114
|
+
delete(res_type, res_id)
|
138
115
|
end
|
139
116
|
else
|
140
117
|
warn "need TYPE and ID or --file option"
|
141
118
|
end
|
142
119
|
end
|
143
120
|
|
144
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
145
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
146
121
|
desc "publish", "Publishes the current version of the given project"
|
147
122
|
long_desc <<-LONGDESC
|
148
|
-
`
|
123
|
+
`xapixctl publish` will publish the given project.
|
149
124
|
|
150
125
|
Examples:
|
151
|
-
\x5> $
|
126
|
+
\x5> $ xapixctl publish -o xapix -p some-project
|
127
|
+
\x5> $ xapixctl publish -p xapix/some-project
|
152
128
|
LONGDESC
|
153
129
|
def publish
|
154
|
-
|
130
|
+
prj_connection.publish do |res|
|
155
131
|
res.on_success { |result| show_deployment_status(result) }
|
156
|
-
res.on_error { |err, result| show_deployment_status(result);
|
132
|
+
res.on_error { |err, result| show_deployment_status(result); exit_with_api_error(err, result) }
|
157
133
|
end
|
158
134
|
end
|
159
135
|
|
160
|
-
option :org, aliases: "-o", desc: "Organization", required: true
|
161
|
-
option :project, aliases: "-p", desc: "Project", required: true
|
162
136
|
desc "logs CORRELATION_ID", "Retrieves the execution logs for the given correlation ID"
|
163
137
|
long_desc <<-LONGDESC
|
164
|
-
`
|
138
|
+
`xapixctl logs CORRELATION_ID` will retrieve execution logs for the given correlation ID.
|
165
139
|
|
166
140
|
The correlation ID is included as X-Correlation-Id header in the response of each request.
|
167
141
|
|
168
142
|
Examples:
|
169
|
-
\x5> $
|
143
|
+
\x5> $ xapixctl logs be9c8608-e291-460d-bc20-5a394c4079d4 -o xapix -p some-project
|
144
|
+
\x5> $ xapixctl logs be9c8608-e291-460d-bc20-5a394c4079d4 -p xapix/some-project
|
170
145
|
LONGDESC
|
171
146
|
def logs(correlation_id)
|
172
|
-
|
173
|
-
|
174
|
-
res.on_error { |err, result| warn_api_error('could not get logs', err, result) }
|
175
|
-
end
|
147
|
+
result = prj_connection.logs(correlation_id)
|
148
|
+
puts result['logs'].to_yaml
|
176
149
|
end
|
177
150
|
|
178
151
|
SUPPORTED_CONTEXTS = ['Project', 'Organization'].freeze
|
152
|
+
|
179
153
|
desc "api-resources", "retrieves a list of all available resource types"
|
180
154
|
def api_resources
|
181
|
-
connection.available_resource_types
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
puts format_str % [desc['type'], desc['context']]
|
188
|
-
end
|
189
|
-
end
|
190
|
-
res.on_error { |err, result| warn_api_error("could not get", err, result) }
|
155
|
+
available_types = connection.available_resource_types
|
156
|
+
format_str = "%20.20s %20.20s %26.26s"
|
157
|
+
puts format_str % ['Type', 'Required Context', '']
|
158
|
+
available_types.sort_by { |desc| desc['type'] }.each do |desc|
|
159
|
+
next unless SUPPORTED_CONTEXTS.include?(desc['context'])
|
160
|
+
puts format_str % [desc['type'], desc['context'], PhoenixClient.supported_type?(desc['type']) ? '' : '(unsupported, update CLI)']
|
191
161
|
end
|
192
162
|
end
|
193
|
-
|
194
|
-
private
|
195
|
-
|
196
|
-
def warn_api_error(text, err, result)
|
197
|
-
details = "\n " + result['errors'].map { |k| k['detail'] }.join("\n ") rescue err.to_s
|
198
|
-
warn "#{text}: #{details}"
|
199
|
-
exit 1
|
200
|
-
end
|
201
|
-
|
202
|
-
def show_deployment_status(result)
|
203
|
-
return unless result && result['project_publication']
|
204
|
-
puts "deployment: #{result.dig('project_publication', 'deployment')}"
|
205
|
-
puts " data api: #{result.dig('project_publication', 'data_api')} (version: #{result.dig('project_publication', 'data_api_version').presence || 'n/a'})"
|
206
|
-
puts " user management: #{result.dig('project_publication', 'user_management')}"
|
207
|
-
if result.dig('project_publication', 'deployment') == 'success'
|
208
|
-
puts " base URL: #{result.dig('project_publication', 'base_url')}"
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
DOCUMENT_STRUCTURE = %w[version kind metadata definition].freeze
|
213
|
-
def resources_from_file(filename)
|
214
|
-
yaml_string = filename == '-' ? $stdin.read : IO.read(filename)
|
215
|
-
yaml_string.split(/^---\s*\n/).map { |yml| Psych.safe_load(yml) }.compact.each do |doc|
|
216
|
-
unless (DOCUMENT_STRUCTURE - doc.keys.map(&:to_s)).empty?
|
217
|
-
warn "does not look like a correct resource definition:"
|
218
|
-
warn doc.inspect
|
219
|
-
exit 1
|
220
|
-
end
|
221
|
-
yield doc
|
222
|
-
end
|
223
|
-
end
|
224
|
-
|
225
|
-
def connection
|
226
|
-
url = options[:xapix_url] || ENV['XAPIX_URL'] || 'https://cloud.xapix.io/'
|
227
|
-
token = options[:xapix_token] || ENV['XAPIX_TOKEN']
|
228
|
-
raise Thor::RequiredArgumentMissingError, "no XAPIX_TOKEN given. Either use --xapix_token [TOKEN] or set environment variable XAPIX_TOKEN (recommended)" if !token
|
229
|
-
PhoenixClient::Connection.new(url, token)
|
230
|
-
end
|
231
163
|
end
|
232
164
|
end
|