3scale_toolbox 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -1
  3. data/lib/3scale_toolbox/cli/error_handler.rb +0 -2
  4. data/lib/3scale_toolbox/commands/3scale_command.rb +0 -4
  5. data/lib/3scale_toolbox/commands/copy_command/copy_service.rb +5 -4
  6. data/lib/3scale_toolbox/commands/copy_command.rb +0 -2
  7. data/lib/3scale_toolbox/commands/help_command.rb +0 -3
  8. data/lib/3scale_toolbox/commands/import_command/import_csv.rb +0 -6
  9. data/lib/3scale_toolbox/commands/import_command/openapi/create_activedocs_step.rb +39 -2
  10. data/lib/3scale_toolbox/commands/import_command/openapi/create_method_step.rb +1 -1
  11. data/lib/3scale_toolbox/commands/import_command/openapi/create_service_step.rb +5 -16
  12. data/lib/3scale_toolbox/commands/import_command/openapi/mapping_rule.rb +11 -1
  13. data/lib/3scale_toolbox/commands/import_command/openapi/step.rb +4 -3
  14. data/lib/3scale_toolbox/commands/import_command/openapi/threescale_api_spec.rb +13 -2
  15. data/lib/3scale_toolbox/commands/import_command/openapi/update_policies_step.rb +63 -14
  16. data/lib/3scale_toolbox/commands/import_command/openapi/update_service_proxy_step.rb +6 -3
  17. data/lib/3scale_toolbox/commands/import_command/openapi.rb +11 -5
  18. data/lib/3scale_toolbox/commands/import_command.rb +0 -2
  19. data/lib/3scale_toolbox/commands/plans_command/apply_command.rb +136 -0
  20. data/lib/3scale_toolbox/commands/plans_command/create_command.rb +100 -0
  21. data/lib/3scale_toolbox/commands/plans_command/delete_command.rb +66 -0
  22. data/lib/3scale_toolbox/commands/plans_command/export/read_app_plan_step.rb +16 -0
  23. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_features_step.rb +16 -0
  24. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_limits_step.rb +19 -0
  25. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_methods_step.rb +50 -0
  26. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_metrics_step.rb +49 -0
  27. data/lib/3scale_toolbox/commands/plans_command/export/read_plan_pricing_rules_step.rb +19 -0
  28. data/lib/3scale_toolbox/commands/plans_command/export/step.rb +95 -0
  29. data/lib/3scale_toolbox/commands/plans_command/export/write_artifacts_file_step.rb +84 -0
  30. data/lib/3scale_toolbox/commands/plans_command/export_command.rb +65 -0
  31. data/lib/3scale_toolbox/commands/plans_command/import/create_or_update_app_plan_step.rb +33 -0
  32. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_features_step.rb +45 -0
  33. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_limits_step.rb +41 -0
  34. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_metrics_step.rb +57 -0
  35. data/lib/3scale_toolbox/commands/plans_command/import/import_plan_pricing_rules_step.rb +39 -0
  36. data/lib/3scale_toolbox/commands/plans_command/import/step.rb +129 -0
  37. data/lib/3scale_toolbox/commands/plans_command/import_command.rb +62 -0
  38. data/lib/3scale_toolbox/commands/plans_command/list_command.rb +63 -0
  39. data/lib/3scale_toolbox/commands/plans_command/show_command.rb +81 -0
  40. data/lib/3scale_toolbox/commands/plans_command.rb +34 -0
  41. data/lib/3scale_toolbox/commands/remote_command.rb +0 -3
  42. data/lib/3scale_toolbox/commands/update_command/update_service.rb +5 -4
  43. data/lib/3scale_toolbox/commands/update_command.rb +0 -2
  44. data/lib/3scale_toolbox/commands.rb +3 -1
  45. data/lib/3scale_toolbox/entities/application_plan.rb +150 -0
  46. data/lib/3scale_toolbox/entities/service.rb +25 -12
  47. data/lib/3scale_toolbox/entities.rb +1 -0
  48. data/lib/3scale_toolbox/helper.rb +41 -0
  49. data/lib/3scale_toolbox/resource_reader.rb +42 -0
  50. data/lib/3scale_toolbox/tasks/copy_app_plans_task.rb +1 -1
  51. data/lib/3scale_toolbox/tasks/copy_limits_task.rb +8 -11
  52. data/lib/3scale_toolbox/tasks/copy_pricingrules_task.rb +5 -3
  53. data/lib/3scale_toolbox/version.rb +1 -1
  54. data/lib/3scale_toolbox.rb +10 -0
  55. metadata +28 -5
  56. data/lib/3scale_toolbox/commands/import_command/openapi/resource_reader.rb +0 -51
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 15a0f5fc1496d1414d2e5a940b1d08d8834dfc23a226f7c3a6d17d3014f1042f
4
- data.tar.gz: e09c49ae0c9023757c2cf22dd2c10a61d009337a67aca4d8080ae2fb7a65eb2d
3
+ metadata.gz: f2de44dc4f50140aaa326b714441c8590eb728f520835905091048911e2cd210
4
+ data.tar.gz: '008edc2978180ab0bda597b545b2c25f09712be036f1b372e6ae6f5c1c83df3e'
5
5
  SHA512:
6
- metadata.gz: dd16657b1d83f114fdaf3d4b0ad1fd39fc08ab3a267e441b332333d22933e620cb7bd1cad48de66711594a9c10fcee8bed894e0b03170baaf6cfee53d7decfd5
7
- data.tar.gz: 16838e3a0c469ed68f4064babce60fe207d77a06c8f869035115422a1d461360da3f2237fd45c6f31d0cd62602646254f4ed2b6a5b25546e318a2afa85e2732a
6
+ metadata.gz: 6db32b4a58ba23a8c0a1902ccf9002812effdefa6946e98883e748406e05c905a075ac13798fbed58461df834c419a4ad66b4c836edf02b510eb61cd8c7770fd
7
+ data.tar.gz: 3eba10df0a824a07d9edd63a88fa7896c1c5fcce7a43dc9e5aefcdb71d955053e858ef6f100319aea53c5a197b38ad0c047232e48c0e993b756ebca280894f08
data/README.md CHANGED
@@ -15,6 +15,8 @@ See the LICENSE and NOTICE files that should have been provided along with this
15
15
  * [Update a service](#update-a-service)
16
16
  * [Import from CSV](#import-from-csv)
17
17
  * [Import from OpenAPI definition](#import-openapi)
18
+ * [Export/Import Application Plan](#export-import-application-plan)
19
+ * Create, Apply, List, Show, Delete [Application plan](docs/app-plan.md)
18
20
  * [Remotes](#remotes)
19
21
  * [Development](#development)
20
22
  * [Testing](#testing)
@@ -50,11 +52,12 @@ COMMANDS
50
52
 
51
53
  OPTIONS
52
54
  -c --config-file=<value> 3scale toolbox configuration file (default:
53
- /home/eguzki/.3scalerc.yaml)
55
+ $HOME/.3scalerc.yaml)
54
56
  -h --help show help for this command
55
57
  -k --insecure Proceed and operate even for server
56
58
  connections otherwise considered insecure
57
59
  -v --version Prints the version of this command
60
+ --verbose Verbose mode
58
61
  ```
59
62
 
60
63
  ### Copy a service
@@ -91,6 +94,7 @@ OPTIONS FOR COPY
91
94
  connections otherwise considered
92
95
  insecure
93
96
  -v --version Prints the version of this command
97
+ --verbose Verbose mode
94
98
  ```
95
99
 
96
100
  ```shell
@@ -131,6 +135,7 @@ OPTIONS FOR UPDATE
131
135
  -k --insecure Proceed and operate even for server
132
136
  connections otherwise considered insecure
133
137
  -v --version Prints the version of this command
138
+ --verbose Verbose mode
134
139
  ```
135
140
 
136
141
  Example:
@@ -182,6 +187,7 @@ OPTIONS FOR IMPORT
182
187
  -k --insecure Proceed and operate even for server
183
188
  connections otherwise considered insecure
184
189
  -v --version Prints the version of this command
190
+ --verbose Verbose mode
185
191
  ```
186
192
 
187
193
  Example:
@@ -198,6 +204,12 @@ Currently, only OpenAPI __2.0__ specification (f.k.a. __swagger__) is supported.
198
204
 
199
205
  [Import from OpenAPI](docs/openapi.md)
200
206
 
207
+ ### Export Import Application Plan
208
+
209
+ A single application plan can be exported/imported as `yaml` format.
210
+
211
+ [Export/Import Application Plan](docs/export-import-app-plan.md)
212
+
201
213
  ### Remotes
202
214
 
203
215
  Manage set of 3scale instances.
@@ -1,5 +1,3 @@
1
- require 'json'
2
-
3
1
  module ThreeScaleToolbox
4
2
  module CLI
5
3
  class ErrorHandler
@@ -1,7 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/version'
3
- require '3scale_toolbox/base_command'
4
-
5
1
  module ThreeScaleToolbox
6
2
  module Commands
7
3
  module ThreeScaleCommand
@@ -1,6 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/base_command'
3
-
4
1
  module ThreeScaleToolbox
5
2
  module Commands
6
3
  module CopyCommand
@@ -33,7 +30,6 @@ module ThreeScaleToolbox
33
30
  puts "new service id #{target_service.id}"
34
31
  context = create_context(source_service, target_service)
35
32
  tasks = [
36
- Tasks::CopyServiceProxyTask.new(context),
37
33
  Tasks::CopyMethodsTask.new(context),
38
34
  Tasks::CopyMetricsTask.new(context),
39
35
  Tasks::CopyApplicationPlansTask.new(context),
@@ -43,6 +39,11 @@ module ThreeScaleToolbox
43
39
  Tasks::CopyPoliciesTask.new(context),
44
40
  Tasks::CopyPricingRulesTask.new(context),
45
41
  Tasks::CopyActiveDocsTask.new(context),
42
+ # Copy proxy must be the last task
43
+ # Proxy update is the mechanism to increase version of the proxy,
44
+ # Hence propagating (mapping rules, poicies, oidc, auth) update to
45
+ # latest proxy config, making available to gateway.
46
+ Tasks::CopyServiceProxyTask.new(context),
46
47
  ]
47
48
  tasks.each(&:call)
48
49
  end
@@ -1,5 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/base_command'
3
1
  require '3scale_toolbox/commands/copy_command/copy_service'
4
2
 
5
3
  module ThreeScaleToolbox
@@ -1,6 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/base_command'
3
-
4
1
  module ThreeScaleToolbox
5
2
  module Commands
6
3
  module HelpCommand
@@ -1,9 +1,3 @@
1
- require 'cri'
2
- require 'uri'
3
- require 'csv'
4
- require '3scale/api'
5
- require '3scale_toolbox/base_command'
6
-
7
1
  module ThreeScaleToolbox
8
2
  module Commands
9
3
  module ImportCommand
@@ -10,7 +10,7 @@ module ThreeScaleToolbox
10
10
  name: api_spec.title,
11
11
  system_name: activedocs_system_name,
12
12
  service_id: service.id,
13
- body: JSON.pretty_generate(resource),
13
+ body: JSON.pretty_generate(rewritten_openapi),
14
14
  description: api_spec.description,
15
15
  published: context[:activedocs_published],
16
16
  skip_swagger_validations: context[:skip_openapi_validation]
@@ -20,7 +20,7 @@ module ThreeScaleToolbox
20
20
  # Make operation indempotent
21
21
  if (errors = res['errors'])
22
22
  raise ThreeScaleToolbox::Error, "ActiveDocs has not been created. #{errors}" \
23
- unless system_name_already_taken_error? errors
23
+ unless ThreeScaleToolbox::Helper.system_name_already_taken_error? errors
24
24
 
25
25
  # if activedocs system_name exists, ignore error, update activedocs
26
26
  puts 'Activedocs exists, update!'
@@ -47,6 +47,43 @@ module ThreeScaleToolbox
47
47
  activedoc['system_name'] == activedocs_system_name
48
48
  end
49
49
  end
50
+
51
+ def rewritten_openapi
52
+ # Updates on copy
53
+ # Other processing steps can work with original openapi spec
54
+ Helper.hash_deep_dup(resource).tap do |activedocs|
55
+ # public production base URL
56
+ URI(service.show_proxy.fetch('endpoint')).tap do |uri|
57
+ activedocs['host'] = "#{uri.host}:#{uri.port}"
58
+ activedocs['schemes'] = [uri.scheme]
59
+ end
60
+
61
+ # the basePath field is updated to a new value only when overriden by optional param
62
+ activedocs['basePath'] = api_spec.public_base_path
63
+
64
+ # security definitions
65
+ # just valid for oauth2 when oidc_issuer_endpoint is supplied
66
+ if !security.nil? && security.type == 'oauth2' && !oidc_issuer_endpoint.nil?
67
+ # authorizationURL
68
+ if %w[implicit accessCode].include?(security.flow)
69
+ activedocs['securityDefinitions'][security.id]['authorizationUrl'] = authorization_url
70
+ end
71
+
72
+ # tokenUrl
73
+ if %w[password application accessCode].include?(security.flow)
74
+ activedocs['securityDefinitions'][security.id]['tokenUrl'] = token_url
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ def authorization_url
81
+ "#{oidc_issuer_endpoint}/protocol/openid-connect/auth"
82
+ end
83
+
84
+ def token_url
85
+ "#{oidc_issuer_endpoint}/protocol/openid-connect/token"
86
+ end
50
87
  end
51
88
  end
52
89
  end
@@ -14,7 +14,7 @@ module ThreeScaleToolbox
14
14
  # Make operation indempotent
15
15
  if (errors = res['errors'])
16
16
  raise ThreeScaleToolbox::Error, "Metohd has not been saved. #{errors}" \
17
- unless system_name_already_taken_error? errors
17
+ unless ThreeScaleToolbox::Helper.system_name_already_taken_error? errors
18
18
 
19
19
  metric_id = method_id_by_system_name[op.method['system_name']]
20
20
  end
@@ -18,7 +18,11 @@ module ThreeScaleToolbox
18
18
  raise unless e.message =~ /"system_name"=>\["has already been taken"\]/
19
19
 
20
20
  # Update service and update context
21
- self.service = Entities::Service.new(id: service_id, remote: threescale_client)
21
+ self.service = Entities::Service.find_by_system_name(remote: threescale_client,
22
+ system_name: service_system_name)
23
+ # It should exist
24
+ raise ThreeScaleToolbox::Error, "Service with system_name: #{service_system_name}, should exist" if service.nil?
25
+
22
26
  service.update_service(service_settings)
23
27
  puts "Updated service id: #{service.id}, name: #{service_name}"
24
28
  end
@@ -29,21 +33,6 @@ module ThreeScaleToolbox
29
33
  target_system_name || service_name.downcase.gsub(/[^\w]/, '_')
30
34
  end
31
35
 
32
- def service_id
33
- @service_id ||= fetch_service_id
34
- end
35
-
36
- def fetch_service_id
37
- # figure out service by system_name
38
- service_found = threescale_client.list_services.find do |svc|
39
- svc['system_name'] == service_system_name
40
- end
41
- # It should exist
42
- raise ThreeScaleToolbox::Error, "Service with system_name: #{service_system_name}, should exist" if service_found.nil?
43
-
44
- service_found['id']
45
- end
46
-
47
36
  def service_settings
48
37
  default_service_settings.tap do |svc|
49
38
  svc['name'] = service_name
@@ -18,7 +18,17 @@ module ThreeScaleToolbox
18
18
 
19
19
  def pattern
20
20
  # apply strict matching
21
- operation[:path] + '$'
21
+ "#{raw_pattern}$"
22
+ end
23
+
24
+ def raw_pattern
25
+ # According OAS 2.0: path MUST begin with a slash
26
+ "#{public_base_path}#{operation[:path]}"
27
+ end
28
+
29
+ def public_base_path
30
+ # remove the last slash of the basePath
31
+ operation[:public_base_path].gsub(%r{/$}, '')
22
32
  end
23
33
 
24
34
  def delta
@@ -43,9 +43,6 @@ module ThreeScaleToolbox
43
43
  context[:api_spec_resource]
44
44
  end
45
45
 
46
- def system_name_already_taken_error?(error)
47
- Array(Hash(error)['system_name']).any? { |msg| msg.match(/has already been taken/) }
48
- end
49
46
 
50
47
  def security
51
48
  api_spec.security
@@ -58,6 +55,10 @@ module ThreeScaleToolbox
58
55
  def default_credentials_userkey
59
56
  context[:default_credentials_userkey]
60
57
  end
58
+
59
+ def override_private_basepath
60
+ context[:override_private_basepath]
61
+ end
61
62
  end
62
63
  end
63
64
  end
@@ -5,8 +5,9 @@ module ThreeScaleToolbox
5
5
  class ThreeScaleApiSpec
6
6
  attr_reader :openapi
7
7
 
8
- def initialize(openapi)
8
+ def initialize(openapi, base_path = nil)
9
9
  @openapi = openapi
10
+ @base_path = base_path
10
11
  end
11
12
 
12
13
  def title
@@ -46,13 +47,23 @@ module ThreeScaleToolbox
46
47
  def operations
47
48
  openapi.operations.map do |op|
48
49
  Operation.new(
49
- path: "#{openapi.base_path}#{op.path}",
50
+ base_path: base_path,
51
+ public_base_path: public_base_path,
52
+ path: op.path,
50
53
  verb: op.verb,
51
54
  operationId: op.operation_id
52
55
  )
53
56
  end
54
57
  end
55
58
 
59
+ def public_base_path
60
+ @base_path || base_path
61
+ end
62
+
63
+ def base_path
64
+ openapi.base_path || '/'
65
+ end
66
+
56
67
  private
57
68
 
58
69
  def parse_security
@@ -17,6 +17,7 @@ module ThreeScaleToolbox
17
17
 
18
18
  add_anonymous_access_policy(policies_settings)
19
19
  add_rh_sso_keycloak_role_check_policy(policies_settings)
20
+ add_url_rewritting_policy(policies_settings)
20
21
 
21
22
  return if source_policies_settings == policies_settings
22
23
 
@@ -47,13 +48,13 @@ module ThreeScaleToolbox
47
48
  if default_credentials_userkey.nil?
48
49
 
49
50
  {
50
- 'name': 'default_credentials',
51
- 'version': 'builtin',
52
- 'configuration': {
53
- 'auth_type': 'user_key',
54
- 'user_key': default_credentials_userkey
51
+ name: 'default_credentials',
52
+ version: 'builtin',
53
+ configuration: {
54
+ auth_type: 'user_key',
55
+ user_key: default_credentials_userkey
55
56
  },
56
- 'enabled': true
57
+ enabled: true
57
58
  }
58
59
  end
59
60
 
@@ -68,20 +69,68 @@ module ThreeScaleToolbox
68
69
 
69
70
  def keycloak_policy
70
71
  {
71
- 'name': 'keycloak_role_check',
72
- 'version': 'builtin',
73
- 'configuration': {
74
- 'type': 'whitelist',
75
- 'scopes': [
72
+ name: 'keycloak_role_check',
73
+ version: 'builtin',
74
+ configuration: {
75
+ type: 'whitelist',
76
+ scopes: [
76
77
  {
77
- 'realm_roles': [],
78
- 'client_roles': security.scopes.map { |scope| { 'name': scope } }
78
+ realm_roles: [],
79
+ client_roles: security.scopes.map { |scope| { 'name': scope } }
79
80
  }
80
81
  ]
81
82
  },
82
- 'enabled': true
83
+ enabled: true
83
84
  }
84
85
  end
86
+
87
+ def add_url_rewritting_policy(policies)
88
+ return if private_base_path == api_spec.public_base_path
89
+
90
+ url_rewritting_policy_idx = policies.find_index do |policy|
91
+ policy['name'] == 'url_rewriting'
92
+ end
93
+
94
+ if url_rewritting_policy_idx.nil?
95
+ policies << url_rewritting_policy
96
+ else
97
+ policies[url_rewritting_policy_idx] = url_rewritting_policy
98
+ end
99
+ end
100
+
101
+ def private_base_path
102
+ override_private_basepath || api_spec.base_path
103
+ end
104
+
105
+ def url_rewritting_policy
106
+ regex = url_rewritting_policy_regex
107
+ replace = url_rewritting_policy_replace
108
+ # If regex has a / at the end, replace must have a / at the end
109
+ replace.concat('/') if regex.end_with?('/') && !replace.end_with?('/')
110
+
111
+ {
112
+ name: 'url_rewriting',
113
+ version: 'builtin',
114
+ configuration: {
115
+ commands: [
116
+ {
117
+ op: 'sub',
118
+ regex: regex,
119
+ replace: replace
120
+ }
121
+ ]
122
+ },
123
+ enabled: true
124
+ }
125
+ end
126
+
127
+ def url_rewritting_policy_regex
128
+ "^#{api_spec.public_base_path}"
129
+ end
130
+
131
+ def url_rewritting_policy_replace
132
+ "#{private_base_path}"
133
+ end
85
134
  end
86
135
  end
87
136
  end
@@ -9,13 +9,16 @@ module ThreeScaleToolbox
9
9
  # Updates Proxy config
10
10
  def call
11
11
  # setting required attrs, operation is idempotent
12
- proxy_settings = {}
12
+ proxy_settings = {
13
+ # Adding harmless attribute to avoid empty body
14
+ # update_proxy cannot be done with empty body
15
+ # and must be done to increase proxy version
16
+ service_id: service.id
17
+ }
13
18
 
14
19
  add_api_backend_settings(proxy_settings)
15
20
  add_security_proxy_settings(proxy_settings)
16
21
 
17
- return unless proxy_settings.size.positive?
18
-
19
22
  res = service.update_proxy proxy_settings
20
23
  if (errors = res['errors'])
21
24
  raise ThreeScaleToolbox::Error, "Service proxy has not been updated. #{errors}"
@@ -2,7 +2,6 @@ require '3scale_toolbox/commands/import_command/openapi/method'
2
2
  require '3scale_toolbox/commands/import_command/openapi/mapping_rule'
3
3
  require '3scale_toolbox/commands/import_command/openapi/operation'
4
4
  require '3scale_toolbox/commands/import_command/openapi/step'
5
- require '3scale_toolbox/commands/import_command/openapi/resource_reader'
6
5
  require '3scale_toolbox/commands/import_command/openapi/threescale_api_spec'
7
6
  require '3scale_toolbox/commands/import_command/openapi/create_method_step'
8
7
  require '3scale_toolbox/commands/import_command/openapi/create_mapping_rule_step'
@@ -18,7 +17,7 @@ module ThreeScaleToolbox
18
17
  module OpenAPI
19
18
  class OpenAPISubcommand < Cri::CommandRunner
20
19
  include ThreeScaleToolbox::Command
21
- include ResourceReader
20
+ include ThreeScaleToolbox::ResourceReader
22
21
 
23
22
  def self.command
24
23
  Cri::Command.define do
@@ -33,6 +32,8 @@ module ThreeScaleToolbox
33
32
  flag nil, 'skip-openapi-validation', 'Skip OpenAPI schema validation'
34
33
  option nil, 'oidc-issuer-endpoint', 'OIDC Issuer Endpoint', argument: :required
35
34
  option nil, 'default-credentials-userkey', 'Default credentials policy userkey', argument: :required
35
+ option nil, 'override-private-basepath', 'Override the basepath for the public URLs', argument: :required
36
+ option nil, 'override-public-basepath', 'Override the basepath for the private URLs', argument: :required
36
37
  param :openapi_resource
37
38
 
38
39
  runner OpenAPISubcommand
@@ -46,9 +47,13 @@ module ThreeScaleToolbox
46
47
  tasks << ThreeScaleToolbox::Tasks::DestroyMappingRulesTask.new(context)
47
48
  tasks << CreateMappingRulesStep.new(context)
48
49
  tasks << CreateActiveDocsStep.new(context)
49
- tasks << UpdateServiceProxyStep.new(context)
50
50
  tasks << UpdateServiceOidcConfStep.new(context)
51
51
  tasks << UpdatePoliciesStep.new(context)
52
+ # Update proxy must be the last step
53
+ # Proxy update is the mechanism to increase version of the proxy,
54
+ # Hence propagating (mapping rules, poicies, oidc, auth) update to
55
+ # latest proxy config, making available to gateway.
56
+ tasks << UpdateServiceProxyStep.new(context)
52
57
 
53
58
  # run tasks
54
59
  tasks.each(&:call)
@@ -64,13 +69,14 @@ module ThreeScaleToolbox
64
69
  openapi_resource = load_resource(arguments[:openapi_resource])
65
70
  {
66
71
  api_spec_resource: openapi_resource,
67
- api_spec: ThreeScaleApiSpec.new(load_openapi(openapi_resource)),
72
+ api_spec: ThreeScaleApiSpec.new(load_openapi(openapi_resource), options[:'override-public-basepath']),
68
73
  threescale_client: threescale_client(fetch_required_option(:destination)),
69
74
  target_system_name: options[:target_system_name],
70
75
  activedocs_published: !options[:'activedocs-hidden'],
71
76
  oidc_issuer_endpoint: options[:'oidc-issuer-endpoint'],
72
77
  default_credentials_userkey: options[:'default-credentials-userkey'],
73
- skip_openapi_validation: options[:'skip-openapi-validation']
78
+ skip_openapi_validation: options[:'skip-openapi-validation'],
79
+ override_private_basepath: options[:'override-private-basepath']
74
80
  }
75
81
  end
76
82
 
@@ -1,5 +1,3 @@
1
- require 'cri'
2
- require '3scale_toolbox/base_command'
3
1
  require '3scale_toolbox/commands/import_command/import_csv'
4
2
  require '3scale_toolbox/commands/import_command/openapi'
5
3
 
@@ -0,0 +1,136 @@
1
+ module ThreeScaleToolbox
2
+ module Commands
3
+ module PlansCommand
4
+ module Apply
5
+ class ApplySubcommand < Cri::CommandRunner
6
+ include ThreeScaleToolbox::Command
7
+
8
+ def self.command
9
+ Cri::Command.define do
10
+ name 'apply'
11
+ usage 'apply [opts] <remote> <service> <plan>'
12
+ summary 'Update application plan'
13
+ description 'Update (create if it does not exist) application plan'
14
+
15
+ option :n, :name, 'Plan name', argument: :required
16
+ flag nil, :default, 'Make default application plan'
17
+ flag nil, :disabled, 'Disables all methods and metrics in this application plan'
18
+ flag nil, :enabled, 'Enable application plan'
19
+ flag :p, :publish, 'Publish application plan'
20
+ flag nil, :hide, 'Hide application plan'
21
+ option nil, 'approval-required', 'Applications require approval. true or false', argument: :required, transform: ThreeScaleToolbox::Helper::BooleanTransformer.new
22
+ option nil, 'cost-per-month', 'Cost per month', argument: :required, transform: method(:Integer)
23
+ option nil, 'setup-fee', 'Setup fee', argument: :required, transform: method(:Integer)
24
+ option nil, 'trial-period-days', 'Trial period days', argument: :required, transform: method(:Integer)
25
+ option nil, 'end-user-required', 'End user required. true or false', argument: :required, transform: ThreeScaleToolbox::Helper::BooleanTransformer.new
26
+ param :remote
27
+ param :service_ref
28
+ param :plan_ref
29
+
30
+ runner ApplySubcommand
31
+ end
32
+ end
33
+
34
+ def run
35
+ validate_option_params
36
+ plan = Entities::ApplicationPlan.find(service: service, ref: plan_ref)
37
+ if plan.nil?
38
+ plan = Entities::ApplicationPlan.create(service: service,
39
+ plan_attrs: create_plan_attrs)
40
+ else
41
+ plan.update(plan_attrs) unless plan_attrs.empty?
42
+ end
43
+
44
+ plan.make_default if option_default
45
+ plan.disable if option_disabled
46
+ plan.enable if option_enabled
47
+
48
+ output_msg_array = ["Applied application plan id: #{plan.id}"]
49
+ output_msg_array << "Default: #{option_default}"
50
+ output_msg_array << 'Disabled' if option_disabled
51
+ output_msg_array << 'Enabled' if option_enabled
52
+ output_msg_array << 'Published' if option_publish
53
+ output_msg_array << 'Hidden' if option_hide
54
+ puts output_msg_array.join('; ')
55
+ end
56
+
57
+ private
58
+
59
+ def validate_option_params
60
+ raise ThreeScaleToolbox::Error, '--disabled and --enabled are mutually exclusive' \
61
+ if option_enabled && option_disabled
62
+
63
+ raise ThreeScaleToolbox::Error, '--publish and --hide are mutually exclusive' \
64
+ if option_publish && option_hide
65
+ end
66
+
67
+ def create_plan_attrs
68
+ plan_attrs.merge('system_name' => plan_ref,
69
+ 'name' => plan_ref) { |_key, oldval, _newval| oldval }
70
+ end
71
+
72
+ def plan_attrs
73
+ plan_basic_attrs.tap do |params|
74
+ params['state'] = 'published' if option_publish
75
+ params['state'] = 'hidden' if option_hide
76
+ end
77
+ end
78
+
79
+ def plan_basic_attrs
80
+ {
81
+ 'name' => options[:name],
82
+ 'approval_required' => options[:'approval-required'],
83
+ 'end_user_required' => options[:'end-user-required'],
84
+ 'cost_per_month' => options[:'cost-per-month'],
85
+ 'setup_fee' => options[:'setup-fee'],
86
+ 'trial_period_days' => options[:'trial-period-days']
87
+ }.compact
88
+ end
89
+
90
+ def option_default
91
+ !options[:default].nil?
92
+ end
93
+
94
+ def option_enabled
95
+ !options[:enabled].nil?
96
+ end
97
+
98
+ def option_disabled
99
+ !options[:disabled].nil?
100
+ end
101
+
102
+ def option_publish
103
+ !options[:publish].nil?
104
+ end
105
+
106
+ def option_hide
107
+ !options[:hide].nil?
108
+ end
109
+
110
+ def service
111
+ @service ||= find_service
112
+ end
113
+
114
+ def find_service
115
+ Entities::Service.find(remote: remote,
116
+ ref: service_ref).tap do |svc|
117
+ raise ThreeScaleToolbox::Error, "Service #{service_ref} does not exist" if svc.nil?
118
+ end
119
+ end
120
+
121
+ def remote
122
+ @remote ||= threescale_client(arguments[:remote])
123
+ end
124
+
125
+ def service_ref
126
+ arguments[:service_ref]
127
+ end
128
+
129
+ def plan_ref
130
+ arguments[:plan_ref]
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end