lex-dynatrace 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b303113698a77c9f3528ffd4a5fa98ecdb807fe6eb7c14c74a4e025bc44b8dd8
4
- data.tar.gz: b837198ac9ef345ac3592e5f60c21cda5afaa97c60e0bdeccab3accecf74eaf3
3
+ metadata.gz: 5778aa9b709e295a7f5f583f5ac14e7ed11284b5eefc2dc313eea4a8c5e2104f
4
+ data.tar.gz: d445a16ae7643ba690aa22b55a5c80ceb82f7f44309a0f59399752961f768ee1
5
5
  SHA512:
6
- metadata.gz: 00374f1c72754647e3e99b75b40cd73bf5db3aea499dbf4f8fa02e508eaf133ad9b348d96cb2756d99bd0f743c41dd7402e3ced29d56b95dde660f1f7a0b4e6c
7
- data.tar.gz: 28c2106f5a55f244a3d1701a08cee0aae62290da953ce689e70b2e74ed53ed9e4cee44cdbc2afb3c04462e7da355383b2322a031e3bba31cc02fe079fca10548
6
+ metadata.gz: be88fb49fd1662c9627917a7668304815cac7b54300038d2fcb33582123c4bfaca2fcc6003d468b5a89d079a6331b381a2edd6792cb6f5212f8b1ea0a63da76d
7
+ data.tar.gz: 314217c27e7b84b5176af02d07df26de3ea8a8231d45bc1a0bcd7eb2b1e5114b28559ae96756d84c85691866ada486c5760b2e948477fe3fc0c602b96383e287
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.0] - 2026-03-27
4
+
5
+ ### Added
6
+ - ActiveGate Tokens: list/get/create/revoke (`/api/v2/activeGateTokens`)
7
+ - Ownership: teams CRUD + validate entity ownership (`/api/v2/ownership`)
8
+ - OTLP: ingest traces, metrics, logs via OpenTelemetry Protocol (`/api/v2/otlp/v1/*`)
9
+ - Extensions20: upload extension zip (multipart)
10
+ - Problems: update/delete comments
11
+ - SecurityProblems: get individual remediation item
12
+ - faraday-multipart dependency for extension upload
13
+ - 31 sub-modules, 129 specs
14
+
3
15
  ## [0.2.0] - 2026-03-27
4
16
 
5
17
  ### Added
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # lex-dynatrace
2
2
 
3
- Legion Extension for the [Dynatrace Environment API v2](https://docs.dynatrace.com/docs/dynatrace-api/environment-api). Multi-module monolith covering 28 API areas with standalone clients.
3
+ Legion Extension for the [Dynatrace Environment API v2](https://docs.dynatrace.com/docs/dynatrace-api/environment-api). Multi-module monolith covering 31 API areas with standalone clients.
4
4
 
5
5
  ## Installation
6
6
 
@@ -51,15 +51,15 @@ entities.get_entity(entity_id: 'HOST-ABC123')
51
51
  |--------|----------|---------|
52
52
  | **Metrics** | `/api/v2/metrics` | `list_descriptors`, `get_descriptor`, `query`, `ingest` |
53
53
  | **Entities** | `/api/v2/entities` | `list_entities`, `get_entity`, `list_entity_types`, `get_entity_type`, `push_custom_device` |
54
- | **Problems** | `/api/v2/problems` | `list_problems`, `get_problem`, `close_problem`, `list_comments`, `create_comment` |
54
+ | **Problems** | `/api/v2/problems` | `list_problems`, `get_problem`, `close_problem`, `list_comments`, `create_comment`, `update_comment`, `delete_comment` |
55
55
  | **Events** | `/api/v2/events` | `list_events`, `get_event`, `ingest_event` |
56
56
  | **Logs** | `/api/v2/logs` | `search_logs`, `aggregate_logs` |
57
57
  | **AuditLogs** | `/api/v2/auditlogs` | `list_audit_logs`, `get_audit_log` |
58
58
  | **ActiveGates** | `/api/v2/activeGates` | `list_active_gates`, `get_active_gate`, `list_update_jobs`, `get_update_job`, `create_update_job`, `delete_update_job`, `get_auto_update_config`, `update_auto_update_config` |
59
- | **Extensions20** | `/api/v2/extensions` | `list_extensions`, `get_extension`, `delete_extension`, `get_extension_version`, `delete_extension_version`, `get_environment_config`, `update_environment_config`, `delete_environment_config`, `list_monitoring_configs`, `get_monitoring_config`, `create_monitoring_config`, `update_monitoring_config`, `delete_monitoring_config` |
59
+ | **Extensions20** | `/api/v2/extensions` | `list_extensions`, `get_extension`, `delete_extension`, `get_extension_version`, `delete_extension_version`, `upload_extension`, `get_environment_config`, `update_environment_config`, `delete_environment_config`, `list_monitoring_configs`, `get_monitoring_config`, `create_monitoring_config`, `update_monitoring_config`, `delete_monitoring_config` |
60
60
  | **Slos** | `/api/v2/slo` | `list_slos`, `get_slo`, `create_slo`, `update_slo`, `delete_slo` |
61
61
  | **Synthetic** | `/api/v2/synthetic` | `list_monitors`, `get_monitor`, `create_monitor`, `update_monitor`, `delete_monitor`, `get_execution`, `trigger_on_demand`, `list_locations`, `get_location` |
62
- | **SecurityProblems** | `/api/v2/securityProblems` | `list_security_problems`, `get_security_problem`, `mute_security_problem`, `unmute_security_problem`, `list_remediations` |
62
+ | **SecurityProblems** | `/api/v2/securityProblems` | `list_security_problems`, `get_security_problem`, `mute_security_problem`, `unmute_security_problem`, `list_remediations`, `get_remediation_item` |
63
63
  | **SettingsObjects** | `/api/v2/settings` | `list_objects`, `get_object`, `create_objects`, `update_object`, `delete_object`, `list_schemas`, `get_schema` |
64
64
  | **NetworkZones** | `/api/v2/networkZones` | `list_network_zones`, `get_network_zone`, `create_network_zone`, `update_network_zone`, `delete_network_zone` |
65
65
  | **Tags** | `/api/v2/tags` | `get_tags`, `add_tags`, `delete_tag` |
@@ -77,6 +77,9 @@ entities.get_entity(entity_id: 'HOST-ABC123')
77
77
  | **OpenPipeline** | `/api/v2/openpipeline/configurations` | `list_pipelines`, `get_pipeline`, `update_pipeline` |
78
78
  | **Documents** | `/api/v2/documents` | `list_documents`, `get_document`, `create_document`, `update_document`, `delete_document` |
79
79
  | **DQL** | `/platform/storage/query/v1/query:execute` | `execute_query` |
80
+ | **ActiveGate Tokens** | `/api/v2/activeGateTokens` | `list_activegate_tokens`, `get_activegate_token`, `create_activegate_token`, `revoke_activegate_token` |
81
+ | **Ownership** | `/api/v2/ownership` | `list_teams`, `get_team`, `create_team`, `update_team`, `delete_team`, `validate_ownership` |
82
+ | **OTLP** | `/api/v2/otlp/v1/*` | `ingest_traces`, `ingest_otlp_metrics`, `ingest_otlp_logs` |
80
83
 
81
84
  ### Unified Client
82
85
 
@@ -118,7 +121,7 @@ When running inside the Legion framework, credentials resolve from settings:
118
121
 
119
122
  ```bash
120
123
  bundle install
121
- bundle exec rspec # 113 specs
124
+ bundle exec rspec # 129 specs
122
125
  bundle exec rubocop # 0 offenses
123
126
  ```
124
127
 
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ['lib']
28
28
 
29
29
  spec.add_dependency 'faraday', '>= 2.0'
30
+ spec.add_dependency 'faraday-multipart', '>= 1.0'
30
31
  spec.add_dependency 'legion-cache', '>= 1.3.11'
31
32
  spec.add_dependency 'legion-crypt', '>= 1.4.9'
32
33
  spec.add_dependency 'legion-data', '>= 1.4.17'
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Dynatrace
6
+ module ActivegateTokens
7
+ module Runners
8
+ module ActivegateTokens
9
+ def list_activegate_tokens(page_size: nil, next_page_key: nil, **opts)
10
+ conn = opts[:connection] || connection(**opts)
11
+ params = {}
12
+ params[:pageSize] = page_size if page_size
13
+ params[:nextPageKey] = next_page_key if next_page_key
14
+ conn.get('api/v2/activeGateTokens', params).body
15
+ end
16
+
17
+ def get_activegate_token(token_id:, **opts)
18
+ conn = opts[:connection] || connection(**opts)
19
+ conn.get("api/v2/activeGateTokens/#{token_id}").body
20
+ end
21
+
22
+ def create_activegate_token(name:, expiration_date: nil, seed_token: nil, **opts)
23
+ conn = opts[:connection] || connection(**opts)
24
+ payload = { name: name }
25
+ payload[:expirationDate] = expiration_date if expiration_date
26
+ payload[:seedToken] = seed_token unless seed_token.nil?
27
+ conn.post('api/v2/activeGateTokens', payload).body
28
+ end
29
+
30
+ def revoke_activegate_token(token_id:, **opts)
31
+ conn = opts[:connection] || connection(**opts)
32
+ conn.delete("api/v2/activeGateTokens/#{token_id}").body
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'activegate_tokens/runners/activegate_tokens'
4
+ require_relative 'helpers/client'
5
+ require_relative 'base_client'
6
+
7
+ module Legion
8
+ module Extensions
9
+ module Dynatrace
10
+ module ActivegateTokens
11
+ class Client < BaseClient
12
+ include Runners::ActivegateTokens
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -32,6 +32,9 @@ require_relative 'hub/runners/hub'
32
32
  require_relative 'open_pipeline/runners/open_pipeline'
33
33
  require_relative 'documents/runners/documents'
34
34
  require_relative 'dql/runners/dql'
35
+ require_relative 'activegate_tokens/runners/activegate_tokens'
36
+ require_relative 'ownership/runners/ownership'
37
+ require_relative 'otlp/runners/otlp'
35
38
  require_relative 'helpers/paginator'
36
39
 
37
40
  module Legion
@@ -69,6 +72,9 @@ module Legion
69
72
  include OpenPipeline::Runners::OpenPipeline
70
73
  include Documents::Runners::Documents
71
74
  include Dql::Runners::Dql
75
+ include ActivegateTokens::Runners::ActivegateTokens
76
+ include Ownership::Runners::Ownership
77
+ include Otlp::Runners::Otlp
72
78
  end
73
79
  end
74
80
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'faraday/multipart'
4
+
3
5
  module Legion
4
6
  module Extensions
5
7
  module Dynatrace
@@ -79,6 +81,19 @@ module Legion
79
81
  conn = opts[:connection] || connection(**opts)
80
82
  conn.delete("api/v2/extensions/#{extension_name}/monitoringConfigurations/#{configuration_id}").body
81
83
  end
84
+
85
+ def upload_extension(file_path:, **opts)
86
+ base = opts[:environment_url] || @opts&.dig(:environment_url)
87
+ token = opts[:api_token] || @opts&.dig(:api_token)
88
+ conn = Faraday.new(url: base) do |f|
89
+ f.request :multipart
90
+ f.response :json
91
+ f.headers['Authorization'] = "Api-Token #{token}" if token
92
+ f.adapter Faraday.default_adapter
93
+ end
94
+ payload = { file: Faraday::Multipart::FilePart.new(file_path, 'application/zip') }
95
+ conn.post('api/v2/extensions', payload).body
96
+ end
82
97
  end
83
98
  end
84
99
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Dynatrace
6
+ module Otlp
7
+ module Runners
8
+ module Otlp
9
+ def ingest_traces(traces:, **)
10
+ conn = otlp_connection(**)
11
+ conn.post('api/v2/otlp/v1/traces', traces).body
12
+ end
13
+
14
+ def ingest_otlp_metrics(metrics:, **)
15
+ conn = otlp_connection(**)
16
+ conn.post('api/v2/otlp/v1/metrics', metrics).body
17
+ end
18
+
19
+ def ingest_otlp_logs(logs:, **)
20
+ conn = otlp_connection(**)
21
+ conn.post('api/v2/otlp/v1/logs', logs).body
22
+ end
23
+
24
+ private
25
+
26
+ def otlp_connection(**opts)
27
+ base = opts[:environment_url] || @opts&.dig(:environment_url)
28
+ token = opts[:api_token] || @opts&.dig(:api_token)
29
+ Faraday.new(url: base) do |f|
30
+ f.request :json
31
+ f.response :json
32
+ f.headers['Authorization'] = "Api-Token #{token}" if token
33
+ f.adapter Faraday.default_adapter
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'otlp/runners/otlp'
4
+ require_relative 'helpers/client'
5
+ require_relative 'base_client'
6
+
7
+ module Legion
8
+ module Extensions
9
+ module Dynatrace
10
+ module Otlp
11
+ class Client < BaseClient
12
+ include Runners::Otlp
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Extensions
5
+ module Dynatrace
6
+ module Ownership
7
+ module Runners
8
+ module Ownership
9
+ def list_teams(page_size: nil, next_page_key: nil, **opts)
10
+ conn = opts[:connection] || connection(**opts)
11
+ params = {}
12
+ params[:pageSize] = page_size if page_size
13
+ params[:nextPageKey] = next_page_key if next_page_key
14
+ conn.get('api/v2/ownership/teams', params).body
15
+ end
16
+
17
+ def get_team(team_id:, **opts)
18
+ conn = opts[:connection] || connection(**opts)
19
+ conn.get("api/v2/ownership/teams/#{team_id}").body
20
+ end
21
+
22
+ def create_team(team:, **opts)
23
+ conn = opts[:connection] || connection(**opts)
24
+ conn.post('api/v2/ownership/teams', team).body
25
+ end
26
+
27
+ def update_team(team_id:, team:, **opts)
28
+ conn = opts[:connection] || connection(**opts)
29
+ conn.put("api/v2/ownership/teams/#{team_id}", team).body
30
+ end
31
+
32
+ def delete_team(team_id:, **opts)
33
+ conn = opts[:connection] || connection(**opts)
34
+ conn.delete("api/v2/ownership/teams/#{team_id}").body
35
+ end
36
+
37
+ def validate_ownership(entity_selector:, **opts)
38
+ conn = opts[:connection] || connection(**opts)
39
+ conn.get('api/v2/ownership/validate', { entitySelector: entity_selector }).body
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'ownership/runners/ownership'
4
+ require_relative 'helpers/client'
5
+ require_relative 'base_client'
6
+
7
+ module Legion
8
+ module Extensions
9
+ module Dynatrace
10
+ module Ownership
11
+ class Client < BaseClient
12
+ include Runners::Ownership
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -46,6 +46,18 @@ module Legion
46
46
  payload[:context] = context if context
47
47
  conn.post("api/v2/problems/#{problem_id}/comments", payload).body
48
48
  end
49
+
50
+ def update_comment(problem_id:, comment_id:, message:, context: nil, **opts)
51
+ conn = opts[:connection] || connection(**opts)
52
+ payload = { message: message }
53
+ payload[:context] = context if context
54
+ conn.put("api/v2/problems/#{problem_id}/comments/#{comment_id}", payload).body
55
+ end
56
+
57
+ def delete_comment(problem_id:, comment_id:, **opts)
58
+ conn = opts[:connection] || connection(**opts)
59
+ conn.delete("api/v2/problems/#{problem_id}/comments/#{comment_id}").body
60
+ end
49
61
  end
50
62
  end
51
63
  end
@@ -47,6 +47,11 @@ module Legion
47
47
  params[:remediationType] = remediation_type if remediation_type
48
48
  conn.get("api/v2/securityProblems/#{security_problem_id}/remediationItems", params).body
49
49
  end
50
+
51
+ def get_remediation_item(security_problem_id:, remediation_id:, **opts)
52
+ conn = opts[:connection] || connection(**opts)
53
+ conn.get("api/v2/securityProblems/#{security_problem_id}/remediationItems/#{remediation_id}").body
54
+ end
50
55
  end
51
56
  end
52
57
  end
@@ -3,7 +3,7 @@
3
3
  module Legion
4
4
  module Extensions
5
5
  module Dynatrace
6
- VERSION = '0.2.0'
6
+ VERSION = '0.3.0'
7
7
  end
8
8
  end
9
9
  end
@@ -31,6 +31,9 @@ require_relative 'dynatrace/hub'
31
31
  require_relative 'dynatrace/open_pipeline'
32
32
  require_relative 'dynatrace/documents'
33
33
  require_relative 'dynatrace/dql'
34
+ require_relative 'dynatrace/activegate_tokens'
35
+ require_relative 'dynatrace/ownership'
36
+ require_relative 'dynatrace/otlp'
34
37
  require_relative 'dynatrace/helpers/paginator'
35
38
  require_relative 'dynatrace/client'
36
39
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lex-dynatrace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -23,6 +23,20 @@ dependencies:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '2.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: faraday-multipart
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
26
40
  - !ruby/object:Gem::Dependency
27
41
  name: legion-cache
28
42
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +155,8 @@ files:
141
155
  - lib/legion/extensions/dynatrace/active_gates.rb
142
156
  - lib/legion/extensions/dynatrace/active_gates/client.rb
143
157
  - lib/legion/extensions/dynatrace/active_gates/runners/active_gates.rb
158
+ - lib/legion/extensions/dynatrace/activegate_tokens.rb
159
+ - lib/legion/extensions/dynatrace/activegate_tokens/runners/activegate_tokens.rb
144
160
  - lib/legion/extensions/dynatrace/attacks.rb
145
161
  - lib/legion/extensions/dynatrace/attacks/client.rb
146
162
  - lib/legion/extensions/dynatrace/attacks/runners/attacks.rb
@@ -195,6 +211,10 @@ files:
195
211
  - lib/legion/extensions/dynatrace/oneagents/runners/oneagents.rb
196
212
  - lib/legion/extensions/dynatrace/open_pipeline.rb
197
213
  - lib/legion/extensions/dynatrace/open_pipeline/runners/open_pipeline.rb
214
+ - lib/legion/extensions/dynatrace/otlp.rb
215
+ - lib/legion/extensions/dynatrace/otlp/runners/otlp.rb
216
+ - lib/legion/extensions/dynatrace/ownership.rb
217
+ - lib/legion/extensions/dynatrace/ownership/runners/ownership.rb
198
218
  - lib/legion/extensions/dynatrace/problems.rb
199
219
  - lib/legion/extensions/dynatrace/problems/client.rb
200
220
  - lib/legion/extensions/dynatrace/problems/runners/problems.rb