3scale_toolbox 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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