oci-logging-analytics-kubernetes-discovery 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +40 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE.txt +36 -0
  6. data/README.md +83 -0
  7. data/Rakefile +15 -0
  8. data/bin/console +17 -0
  9. data/bin/oci-loganalytics-kubernetes-discovery +184 -0
  10. data/bin/setup +12 -0
  11. data/lib/config/oci_client_retry_config.rb +34 -0
  12. data/lib/discover/infrastructure.rb +122 -0
  13. data/lib/discover/object.rb +347 -0
  14. data/lib/dto/infra/cluster_entity_payload.rb +22 -0
  15. data/lib/dto/infra/load_balancers_entity_payload.rb +22 -0
  16. data/lib/dto/infra/node_pool_entity_payload.rb +24 -0
  17. data/lib/dto/infra/subnet_entity_payload.rb +22 -0
  18. data/lib/dto/infra/vcn_entity_payload.rb +22 -0
  19. data/lib/dto/infra_objects_payload.rb +40 -0
  20. data/lib/dto/kubernetes_objects_payload.rb +58 -0
  21. data/lib/dto/payload/log_events.rb +26 -0
  22. data/lib/dto/payload/log_events_json.rb +22 -0
  23. data/lib/dto/state.rb +19 -0
  24. data/lib/enum/auth_type_enum.rb +9 -0
  25. data/lib/enum/infrastructure_resource_discovery.rb +9 -0
  26. data/lib/enum/kubernetes_objects_enum.rb +22 -0
  27. data/lib/enum/object_client_mapping_enum.rb +21 -0
  28. data/lib/infra_resources.rb +91 -0
  29. data/lib/objects_resources.rb +174 -0
  30. data/lib/oci_loganalytics_resources_discovery.rb +293 -0
  31. data/lib/util/kube_client.rb +141 -0
  32. data/lib/util/kubectl_ops.rb +229 -0
  33. data/lib/util/log_analytics.rb +154 -0
  34. data/lib/util/logging.rb +96 -0
  35. data/lib/util/oci_clients.rb +228 -0
  36. data/lib/util/state_manager.rb +61 -0
  37. data/lib/util/string_utils.rb +16 -0
  38. data/lib/version.rb +6 -0
  39. data/oci-logging-analytics-kubernetes-discovery.gemspec +45 -0
  40. metadata +324 -0
@@ -0,0 +1,21 @@
1
+ ## Copyright (c) 2024 Oracle and/or its affiliates.
2
+ ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
3
+
4
+ module Enum
5
+ module ObjectClientMapingEnum
6
+ NODES = :core_client
7
+ PODS = :core_client
8
+ SERVICES = :core_client
9
+ ENDPOINT_SLICES = :discover_v1_client
10
+ DEPLOYMENTS = :apps_client
11
+ REPLICA_SETS = :apps_client
12
+ DAEMON_SETS = :apps_client
13
+ CRON_JOBS = :batch_client
14
+ JOBS = :batch_client
15
+ STATEFUL_SETS = :apps_client
16
+ EVENTS = :core_client
17
+ NAMESPACES = :core_client
18
+ PERSISTENT_VOLUMES = :core_client
19
+ PERSISTENT_VOLUME_CLAIMS = :core_client
20
+ end
21
+ end
@@ -0,0 +1,91 @@
1
+ ## Copyright (c) 2024 Oracle and/or its affiliates.
2
+ ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
3
+
4
+ # Infra
5
+ require_relative './discover/infrastructure'
6
+
7
+ # Objects
8
+ require_relative './dto/infra_objects_payload'
9
+
10
+ # DTOs
11
+ require_relative './dto/infra/cluster_entity_payload'
12
+ require_relative './dto/infra/subnet_entity_payload'
13
+ require_relative './dto/infra/vcn_entity_payload'
14
+ require_relative './dto/infra/load_balancers_entity_payload'
15
+ require_relative './dto/infra/node_pool_entity_payload'
16
+
17
+ # Util
18
+ require_relative './util/logging'
19
+
20
+ module InfraResources
21
+ extend Util::Logging
22
+ extend Discover::Infrastructure
23
+
24
+ module_function
25
+
26
+ def get_infra_resources(auth_object, cluster_id)
27
+ # Fetch cluster details using cluster OCID provided as argument during program run
28
+ logger.debug('Fetching cluster details.')
29
+ ce_response = Discover::Infrastructure.fetch_cluster_details(auth_object, cluster_id)
30
+ cluster_entity_payload = Dto::Infra::ClusterEntityPayload.new(ce_response.name, ce_response.id)
31
+
32
+ # Fetch VCN associated with cluster
33
+ logger.debug('Fetching virtual cloud network details.')
34
+ vcn_response = Discover::Infrastructure.fetch_vcn_response(auth_object, ce_response.vcn_id)
35
+ vcn_entity_payload = Dto::Infra::VcnEntityPayload.new(vcn_response.display_name, vcn_response.id)
36
+
37
+ # Fetch subnets falling under same compartment as that of cluster using VCN OCID
38
+ logger.debug('Fetching subnet details.')
39
+ subnet_response = Discover::Infrastructure.fetch_subnet_list_response(auth_object, ce_response.compartment_id, vcn_response.id)
40
+
41
+ # Loop subnet response to get individual subnets.
42
+ subnet_entity_payload = []
43
+ subnet_response.each do |subnet|
44
+ next if subnet.nil?
45
+
46
+ subnet_entity_payload.push(Dto::Infra::SubnetEntityPayload.new(subnet.display_name, subnet.id))
47
+ end
48
+
49
+ # Use resource search query to fetch load balancers associated with cluster OCID
50
+ logger.debug('Fetching load balancers associated with cluster.')
51
+ free_text_response = Discover::Infrastructure.fetch_free_text_details(auth_object, ce_response.id)
52
+
53
+ load_balancer_entity_payload = nil
54
+ free_text_response.items.each do |item|
55
+ next if item.nil?
56
+
57
+ next unless item.resource_type == 'LoadBalancer'
58
+
59
+ logger.info('Fetching load balancers details.')
60
+ lb_response = Discover::Infrastructure.fetch_load_balancer_details(auth_object, item.identifier)
61
+ lb_compartment_id = lb_response.defined_tags['Oracle-Tags']['CreatedBy']
62
+ if lb_compartment_id == ce_response.id
63
+ load_balancer_entity_payload = Dto::Infra::LoadBalancerEntityPayload.new(lb_response.display_name, lb_compartment_id)
64
+ end
65
+ end
66
+
67
+ # Iterate through all the compartments (starting from root tenancy level) and fetch node pools
68
+ # associated with the cluster OCID
69
+ node_pool_entity_payload = []
70
+ compartment_list_response = Discover::Infrastructure.fetch_compartment_list(auth_object, auth_object[:oci_config].tenancy)
71
+ compartment_list_response.each do |compartment|
72
+ next if compartment.nil?
73
+
74
+ node_pool_response = Discover::Infrastructure.fetch_node_pool_lists(auth_object, compartment.id, ce_response.id)
75
+
76
+ node_pool_response.each do |node_pool|
77
+ next if node_pool.nil?
78
+
79
+ node_pool_entity_payload.push(Dto::Infra::NodePoolEntityPayload.new(node_pool.node_image_name, node_pool.node_image_id, node_pool.compartment_id))
80
+ end
81
+ end
82
+
83
+ Dto::InfraObjectsPayLoad.new(
84
+ cluster_entity_payload, vcn_entity_payload, subnet_entity_payload,
85
+ load_balancer_entity_payload, node_pool_entity_payload
86
+ )
87
+ rescue StandardError => e
88
+ logger.error("Error in getting infrastructure resources: #{e}")
89
+ raise
90
+ end
91
+ end
@@ -0,0 +1,174 @@
1
+ ## Copyright (c) 2024 Oracle and/or its affiliates.
2
+ ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
3
+
4
+ # Objects
5
+ require_relative './discover/object'
6
+ require_relative './dto/kubernetes_objects_payload'
7
+
8
+ # Enum
9
+ require_relative './enum/kubernetes_objects_enum'
10
+ require_relative './enum/object_client_mapping_enum'
11
+
12
+ # Util
13
+ require_relative './util/logging'
14
+ require_relative './util/kube_client'
15
+
16
+ # Threading
17
+ require 'concurrent'
18
+
19
+ module ObjectsResources
20
+ extend Util::Logging
21
+
22
+ module_function
23
+
24
+ attr_accessor :nodes, :pods, :services, :endpoint_slices, :deployments, :replica_sets,
25
+ :daemon_sets, :cron_jobs, :jobs, :stateful_sets, :events, :namespaces,
26
+ :persistent_volumes, :persistent_volume_claims
27
+
28
+ Cluster = Struct.new(:id, :name)
29
+
30
+ def get_objects_resources_helper(cluster_id, cluster_name, app_config)
31
+ cluster = Cluster.new(cluster_id, cluster_name)
32
+
33
+ enable_threading = app_config[:enable_threading]
34
+ if enable_threading
35
+ thread_count = app_config[:thread_count]
36
+ work_queue_size = app_config[:work_queue_size]
37
+
38
+ begin
39
+ thread_pool = Concurrent::FixedThreadPool.new(
40
+ Concurrent.processor_count,
41
+ min_threads: thread_count,
42
+ max_threads: thread_count,
43
+ max_queue: work_queue_size,
44
+ fallback_policy: :abort
45
+ )
46
+
47
+ logger.debug("Thread count set to '#{thread_count}' for fixed thread pool.")
48
+ logger.debug("Work queue size set to '#{work_queue_size}'.")
49
+ rescue StandardError => e
50
+ logger.warn("Error occurred while creating thread pool. Falling back to sequential execution. Error: #{error}")
51
+ enable_threading = false
52
+ end
53
+ end
54
+
55
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
56
+
57
+ begin
58
+ payload_executors = Enum::KubernetesObjectsEnum.constants(false).map do |object_type|
59
+ if Enum::ObjectClientMapingEnum.const_defined? object_type
60
+ if enable_threading == true
61
+ Concurrent::Future.execute({ executor: thread_pool }) do
62
+ get_objects_resources(object_type)
63
+ end
64
+ else
65
+ get_objects_resources(object_type)
66
+ end
67
+ end
68
+ end
69
+
70
+ if enable_threading
71
+ payload_executors.map do |executor|
72
+ executor.value! unless executor.nil?
73
+ end
74
+ end
75
+ rescue StandardError => e
76
+ logger.error("Error while fetching object details - #{e}")
77
+ raise
78
+ end
79
+
80
+ end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
81
+ logger.debug("Time elapsed in collecting objects: #{(end_time - start_time).round(2)} seconds.")
82
+
83
+ kubernetes_objects_processed = Dto::KubernetesObjectsPayLoad.new(
84
+ cluster, @nodes[:processed], @pods[:processed], @services[:processed], @endpoint_slices[:processed],
85
+ @deployments[:processed], @replica_sets[:processed], @daemon_sets[:processed], @cron_jobs[:processed],
86
+ @jobs[:processed], @stateful_sets[:processed], @events[:processed], @namespaces[:processed]
87
+ )
88
+
89
+ kubernetes_objects_raw_responses = {
90
+ nodes: @nodes[:raw],
91
+ pods: @pods[:raw],
92
+ services: @services[:raw],
93
+ endpoint_slices: @endpoint_slices[:raw],
94
+ deployments: @deployments[:raw],
95
+ replica_sets: @replica_sets[:raw],
96
+ daemon_sets: @daemon_sets[:raw],
97
+ cron_jobs: @cron_jobs[:raw],
98
+ jobs: @jobs[:raw],
99
+ stateful_sets: @stateful_sets[:raw],
100
+ events: @events[:raw],
101
+ namespaces: @namespaces[:raw],
102
+ persistent_volumes: @persistent_volumes[:raw],
103
+ persistent_volume_claims: @persistent_volume_claims[:raw]
104
+ }
105
+
106
+ { processed_objects: kubernetes_objects_processed, raw_response: kubernetes_objects_raw_responses }
107
+ end
108
+
109
+ def get_objects_resources(object_type)
110
+ object_payload = object_type.downcase.to_s
111
+
112
+ case object_payload
113
+ when Enum::KubernetesObjectsEnum::CRON_JOBS.to_s
114
+ @cron_jobs = Discover::Object.get_cron_jobs
115
+ log_individual_payload_items(object_type.to_s, @cron_jobs[:processed])
116
+ when Enum::KubernetesObjectsEnum::DAEMON_SETS.to_s
117
+ @daemon_sets = Discover::Object.get_daemon_sets
118
+ log_individual_payload_items(object_type.to_s, @daemon_sets[:processed])
119
+ when Enum::KubernetesObjectsEnum::DEPLOYMENTS.to_s
120
+ @deployments = Discover::Object.get_deployments
121
+ log_individual_payload_items(object_type.to_s, @deployments[:processed])
122
+ when Enum::KubernetesObjectsEnum::ENDPOINT_SLICES.to_s
123
+ @endpoint_slices = Discover::Object.get_endpoint_slices
124
+ log_individual_payload_items(object_type.to_s, @endpoint_slices[:processed])
125
+ when Enum::KubernetesObjectsEnum::JOBS.to_s
126
+ @jobs = Discover::Object.get_jobs
127
+ log_individual_payload_items(object_type.to_s, @jobs[:processed])
128
+ when Enum::KubernetesObjectsEnum::NODES.to_s
129
+ @nodes = Discover::Object.get_nodes
130
+ log_individual_payload_items(object_type.to_s, @nodes[:processed])
131
+ when Enum::KubernetesObjectsEnum::PODS.to_s
132
+ @pods = Discover::Object.get_pods
133
+ log_individual_payload_items(object_type.to_s, @pods[:processed])
134
+ when Enum::KubernetesObjectsEnum::REPLICA_SETS.to_s
135
+ @replica_sets = Discover::Object.get_replica_sets
136
+ log_individual_payload_items(object_type.to_s, @replica_sets[:processed])
137
+ when Enum::KubernetesObjectsEnum::SERVICES.to_s
138
+ @services = Discover::Object.get_services
139
+ log_individual_payload_items(object_type.to_s, @services[:processed])
140
+ when Enum::KubernetesObjectsEnum::STATEFUL_SETS.to_s
141
+ @stateful_sets = Discover::Object.get_stateful_sets
142
+ log_individual_payload_items(object_type.to_s, @stateful_sets[:processed])
143
+ when Enum::KubernetesObjectsEnum::EVENTS.to_s
144
+ @events = Discover::Object.get_events
145
+ log_individual_payload_items(object_type.to_s, @events[:processed])
146
+ when Enum::KubernetesObjectsEnum::NAMESPACES.to_s
147
+ @namespaces = Discover::Object.get_namespaces
148
+ log_individual_payload_items(object_type.to_s, @namespaces[:processed])
149
+ when Enum::KubernetesObjectsEnum::PERSISTENT_VOLUMES.to_s
150
+ @persistent_volumes = Discover::Object.get_persistent_volumes
151
+ unless @persistent_volumes[:processed].nil?
152
+ log_individual_payload_items(object_type.to_s, @persistent_volumes[:processed])
153
+ end
154
+ when Enum::KubernetesObjectsEnum::PERSISTENT_VOLUME_CLAIMS.to_s
155
+ @persistent_volume_claims = Discover::Object.get_persistent_volume_claims
156
+ unless @persistent_volume_claims[:processed].nil?
157
+ log_individual_payload_items(object_type.to_s, @persistent_volume_claims[:processed])
158
+ end
159
+ else
160
+ logger.error("Object type '#{object_payload}' not supported")
161
+ end
162
+ end
163
+
164
+ def log_individual_payload_items(object_name, arr)
165
+ logger.info("Total count of '#{object_name}': #{arr.length}")
166
+
167
+ return if arr.empty?
168
+
169
+ logger.trace("Iterating over each '#{object_name}'.")
170
+ arr.each do |item|
171
+ logger.trace("#{object_name}: #{item.to_h.to_json}")
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,293 @@
1
+ ## Copyright (c) 2024 Oracle and/or its affiliates.
2
+ ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
3
+
4
+ # Libraries
5
+ require 'kubeclient'
6
+ require 'zip'
7
+ require 'yajl'
8
+
9
+ # Resources
10
+ require_relative './infra_resources'
11
+ require_relative './objects_resources'
12
+
13
+ # Util
14
+ require_relative './util/logging'
15
+ require_relative './util/kube_client'
16
+ require_relative './util/oci_clients'
17
+ require_relative './util/log_analytics'
18
+ require_relative './util/state_manager'
19
+
20
+ # DTO
21
+ require_relative './dto/payload/log_events'
22
+ require_relative './dto/payload/log_events_json'
23
+
24
+ module OCI
25
+ class << self
26
+ attr_accessor :sdk_name
27
+
28
+ # Defines the logger used for debugging for the OCI module.
29
+ # For example, log to STDOUT by setting this to Logger.new(STDOUT).
30
+ #
31
+ # @return [Logger]
32
+ attr_accessor :logger
33
+ end
34
+ end
35
+
36
+ module OciLogAnalyticsResourcesDiscovery
37
+ extend Util::Logging
38
+
39
+ module_function
40
+
41
+ attr_accessor :cluster_config_hash, :auth_config_hash, :kube_config_hash, :app_config_hash,
42
+ :auth_object, :kube_clients, :oci_clients, :snapshot_id
43
+
44
+ @@oci_la_log_source_name = 'Kubernetes Objects Discovery Payload Logs'
45
+ @@oci_la_log_path = 'UNDEFINED'
46
+
47
+ def initialize(cluster_config_hash:, auth_config_hash:, kube_config_hash:, app_config_hash:)
48
+ @cluster_config_hash = cluster_config_hash
49
+ @auth_config_hash = auth_config_hash
50
+ @kube_config_hash = kube_config_hash
51
+ @app_config_hash = app_config_hash
52
+
53
+ # OCI.logger = Util::Logging.logger
54
+
55
+ get_auth_object
56
+
57
+ options = { mode: app_config_hash[:mode] }
58
+ get_oci_clients(options)
59
+
60
+ if @app_config_hash[:mode] == 'object'
61
+ @snapshot_id = Time.now.to_i
62
+ get_kube_clients
63
+ Util::StateManager.init(@cluster_config_hash[:kubernetes_resourcename_prefix], @cluster_config_hash[:kubernetes_cluster_namespace])
64
+ Util::KubectlOps.set_chunk_limit @app_config_hash[:chunk_limit]
65
+ logger.debug("Chunk limit set to - #{@app_config_hash[:chunk_limit]}")
66
+ end
67
+ end
68
+
69
+ def initiate_infra_discovery
70
+ logger.info('Initiating Kubernetes infrastructure discovery.')
71
+ begin
72
+ infra_objects_payload = get_infra_resources_payload
73
+ rescue StandardError => e
74
+ logger.error("Error occurred while fetching infrastructure resources. Error: #{e}")
75
+ raise StandardError, 'Error occurred while fetching infrastructure resources.'
76
+ end
77
+
78
+ logger.info('Infrastructure discovery payload created.')
79
+ logger.trace("Infrastructure discovery payload: \n#{Yajl.dump(infra_objects_payload.to_hash)}")
80
+
81
+ if @app_config_hash[:skip_upload]
82
+ logger.warn('--skip_upload Flag is set: Skipping payload upload to OCI Logging Analytics.')
83
+ else
84
+ if !infra_objects_payload.nil?
85
+ # TODO: Upload implemetation pending.
86
+ else
87
+ logger.warn('No infrastructure objects discovered.')
88
+ end
89
+ end
90
+ end
91
+
92
+ def initiate_object_discovery
93
+ kubernetes_objects_payload = get_objects_resources_payload
94
+ if @app_config_hash[:collect_warning_events_only]
95
+ logger.info('Only Warning event logs will be collected as the following flag is set: --collect_warning_events_only')
96
+ end
97
+ kubernetes_objects_payload = filter_event_logs(kubernetes_objects_payload,
98
+ @app_config_hash[:collect_warning_events_only])
99
+
100
+ logger.info('Kubernetes objects discovery payload created.')
101
+ logger.trace("Object Discovery Payload: \n#{Yajl.dump(kubernetes_objects_payload[:processed_objects].to_hash)}")
102
+ logger.trace("Object Log Collection Payload: \n#{Yajl.dump(kubernetes_objects_payload[:raw_response].to_hash)}")
103
+
104
+ if @app_config_hash[:skip_upload]
105
+ logger.warn('--skip_upload Flag is set: Skipping payload upload to OCI logging analytics.')
106
+ else
107
+ upload_failure = false
108
+
109
+ begin
110
+ # Upload object logs with relevant header parameters
111
+ logger.info('Uploading Object Logs to OCI')
112
+ object_logs_opts = {
113
+ payload_type: 'ZIP',
114
+ discovery_data_type: 'K8S_OBJECTS',
115
+ opc_meta_properties: "cluster-entity-id:#{@cluster_config_hash[:oci_la_cluster_entity_id]};sub-type:object_logs;snapshot-id:#{@snapshot_id};log-group-id:#{@cluster_config_hash[:oci_la_log_group_id]};cluster-id:#{@cluster_config_hash[:kubernetes_cluster_id]};cluster-name:#{@cluster_config_hash[:kubernetes_cluster_name]}"
116
+ }
117
+ zip_object_log_payload = get_zippedstream(kubernetes_objects_payload)
118
+ upload_data_via_discovery_api(zip_object_log_payload, object_logs_opts) unless zip_object_log_payload.nil?
119
+ logger.info('Successfully uploaded object logs to OCI')
120
+
121
+ # Update the Events tracker config map only after successful objects logs upload
122
+ Util::StateManager.update_state_configmap
123
+ rescue StandardError
124
+ logger.error('Error occurred while uploading object logs to OCI')
125
+ upload_failure = true
126
+ end
127
+
128
+ unless @cluster_config_hash[:oci_la_cluster_entity_id].nil?
129
+ begin
130
+ # Upload object discovery payload with relevant header parameters
131
+ logger.info('Uploading Object Discovery Payload to OCI')
132
+ object_discovery_opts = {
133
+ payload_type: 'JSON',
134
+ discovery_data_type: 'K8S_OBJECTS',
135
+ opc_meta_properties: "cluster-entity-id:#{@cluster_config_hash[:oci_la_cluster_entity_id]};sub-type:discovery_payload;cluster-id:#{@cluster_config_hash[:kubernetes_cluster_id]};cluster-name:#{@cluster_config_hash[:kubernetes_cluster_name]}"
136
+ }
137
+ json_object_discovery_payload = Yajl.dump(kubernetes_objects_payload[:processed_objects].to_hash)
138
+ upload_data_via_discovery_api(json_object_discovery_payload, object_discovery_opts)
139
+ logger.info('Successfully uploaded object discovery payload to OCI')
140
+ rescue StandardError
141
+ logger.error('Error occurred while uploading object discovery payload to OCI')
142
+ upload_failure = true
143
+ end
144
+ end
145
+
146
+ raise StandardError, 'Error occurred while uploading payloads to OCI' if upload_failure
147
+ end
148
+ end
149
+
150
+ def get_auth_object
151
+ begin
152
+ Util::OCIClients.initialize_auth_config(@auth_config_hash)
153
+ rescue StandardError => e
154
+ logger.error("Error occurred in creating authentication object - #{e}")
155
+ raise e
156
+ end
157
+ @auth_object = Util::OCIClients.get_auth_config_object
158
+ logger.debug('Successfully loaded the OCI auth config.')
159
+ end
160
+
161
+ def get_kube_clients
162
+ begin
163
+ Util::KubeClient.create_clients(@kube_config_hash)
164
+ rescue StandardError => e
165
+ logger.error("Error occurred in creating kubeclients - #{e}")
166
+ raise e
167
+ end
168
+ @kube_clients = Util::KubeClient.get_clients
169
+ logger.debug('Kubeclients created successfully.')
170
+ end
171
+
172
+ def get_oci_clients(options)
173
+ begin
174
+ Util::OCIClients.create_clients(@auth_object, options)
175
+ rescue StandardError => e
176
+ logger.error("Error occurred in creating OCI clients - #{e}")
177
+ raise e
178
+ end
179
+ @oci_clients = Util::OCIClients.get_clients
180
+ logger.debug('OCI clients created successfully.')
181
+ end
182
+
183
+ def get_infra_resources_payload
184
+ logger.debug('Discovering Infrastructure Resources')
185
+ infra_resources_payload = nil
186
+
187
+ unless @auth_object.nil?
188
+ begin
189
+ infra_resources_payload = InfraResources.get_infra_resources(@auth_object, @cluster_config_hash[:oci_la_cluster_entity_id])
190
+ rescue StandardError => e
191
+ logger.error("Error in getting infrastructure resources: #{e}")
192
+ end
193
+ end
194
+ infra_resources_payload
195
+ end
196
+
197
+ def get_objects_resources_payload
198
+ logger.info('Discovering Kubernetes Objects.')
199
+ raise StandardError, 'Kubeclients not initialized.' if @kube_clients.nil?
200
+
201
+ ObjectsResources.get_objects_resources_helper(
202
+ @cluster_config_hash[:kubernetes_cluster_id],
203
+ @cluster_config_hash[:kubernetes_cluster_name],
204
+ @app_config_hash
205
+ )
206
+ end
207
+
208
+ def filter_event_logs(kubernetes_objects_payload, collect_warning_events_only)
209
+ cluster_events_processed_time = Util::StateManager.state.last_timestamp
210
+ new_processed_time = cluster_events_processed_time
211
+ filtered_events = []
212
+ logger.info("Filtering events with EPOCH cut-off : #{cluster_events_processed_time} - (#{Time.at(cluster_events_processed_time).getutc})")
213
+ begin
214
+ eventlist_response = JSON.parse(kubernetes_objects_payload[:raw_response][:events], symbolize_names: true)
215
+ eventslist = eventlist_response[:items]
216
+ eventslist.each do |event|
217
+ # Skip all non warning events if collect_warning_events_only == true
218
+ next if collect_warning_events_only && event[:type] != 'Warning'
219
+
220
+ # if lastTimeStamp is present, use it, otherwise fallback to creationTimestamp
221
+ event_timestamp = if !event[:lastTimestamp].nil?
222
+ event[:lastTimestamp]
223
+ elsif !event[:metadata][:creationTimestamp].nil?
224
+ event[:metadata][:creationTimestamp]
225
+ else
226
+ logger.warn("Not able to find event timestamp in following event (uid) - #{event[:uid]}")
227
+ next
228
+ end
229
+
230
+ event_timestamp = Time.parse(event_timestamp).to_i
231
+
232
+ if event_timestamp > cluster_events_processed_time
233
+ filtered_events.push(event)
234
+ new_processed_time = event_timestamp if event_timestamp > new_processed_time
235
+ end
236
+ end
237
+ logger.info("Event Filter Stats: #{filtered_events.length} out of #{eventslist.length} events included.")
238
+ Util::StateManager.state.last_timestamp = new_processed_time
239
+ rescue StandardError => e
240
+ logger.error("Failed to filter event logs - #{e}")
241
+ raise e
242
+ end
243
+ eventlist_response[:items] = filtered_events
244
+ kubernetes_objects_payload[:raw_response][:events] = JSON.dump(eventlist_response)
245
+ kubernetes_objects_payload
246
+ end
247
+
248
+ def get_zippedstream(kubernetes_object_payload)
249
+ logger.debug('Creating Zipped stream for object log collection payload')
250
+ begin
251
+ zippedstream = Zip::OutputStream.write_buffer do |zos|
252
+ kubernetes_object_payload[:raw_response].each do |key, value|
253
+ next if value.nil? || value.empty?
254
+
255
+ next_entry = "k8s.#{key}.json"
256
+ zos.put_next_entry(next_entry)
257
+
258
+ zos.write(value)
259
+ end
260
+ end
261
+ zippedstream.rewind
262
+ rescue StandardError => e
263
+ logger.error("Failed to generate zipped stream of discovery payload - #{e}")
264
+ raise e
265
+ end
266
+ zippedstream
267
+ end
268
+
269
+ def upload_data_via_discovery_api(payload, opts)
270
+ response = if @app_config_hash[:enable_raw_request]
271
+ Util::LogAnalytics.upload_discovery_data_raw_request(@cluster_config_hash[:oci_la_namespace],
272
+ payload,
273
+ opts,
274
+ @auth_object)
275
+ else
276
+ Util::LogAnalytics.upload_discovery_data(@cluster_config_hash[:oci_la_namespace],
277
+ payload,
278
+ opts)
279
+ end
280
+ unless response.nil?
281
+ resp_headers = response.headers
282
+ logger.info("Response OPC object ID: #{resp_headers['opc-object-id']}")
283
+ logger.info("Response OPC request ID: #{resp_headers['opc-request-id']}")
284
+ end
285
+ rescue OCI::Errors::ServiceError => e
286
+ error_code = e.status_code
287
+ logger.error("Error code '#{error_code}' encountered while uploading payload, error: #{e}")
288
+ raise e
289
+ rescue StandardError => e
290
+ logger.error("Error in uploading data - #{e}")
291
+ raise e
292
+ end
293
+ end