oci-logging-analytics-kubernetes-discovery 1.0.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 (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