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.
- checksums.yaml +7 -0
- data/.gitignore +40 -0
- data/.travis.yml +6 -0
- data/Gemfile +7 -0
- data/LICENSE.txt +36 -0
- data/README.md +83 -0
- data/Rakefile +15 -0
- data/bin/console +17 -0
- data/bin/oci-loganalytics-kubernetes-discovery +184 -0
- data/bin/setup +12 -0
- data/lib/config/oci_client_retry_config.rb +34 -0
- data/lib/discover/infrastructure.rb +122 -0
- data/lib/discover/object.rb +347 -0
- data/lib/dto/infra/cluster_entity_payload.rb +22 -0
- data/lib/dto/infra/load_balancers_entity_payload.rb +22 -0
- data/lib/dto/infra/node_pool_entity_payload.rb +24 -0
- data/lib/dto/infra/subnet_entity_payload.rb +22 -0
- data/lib/dto/infra/vcn_entity_payload.rb +22 -0
- data/lib/dto/infra_objects_payload.rb +40 -0
- data/lib/dto/kubernetes_objects_payload.rb +58 -0
- data/lib/dto/payload/log_events.rb +26 -0
- data/lib/dto/payload/log_events_json.rb +22 -0
- data/lib/dto/state.rb +19 -0
- data/lib/enum/auth_type_enum.rb +9 -0
- data/lib/enum/infrastructure_resource_discovery.rb +9 -0
- data/lib/enum/kubernetes_objects_enum.rb +22 -0
- data/lib/enum/object_client_mapping_enum.rb +21 -0
- data/lib/infra_resources.rb +91 -0
- data/lib/objects_resources.rb +174 -0
- data/lib/oci_loganalytics_resources_discovery.rb +293 -0
- data/lib/util/kube_client.rb +141 -0
- data/lib/util/kubectl_ops.rb +229 -0
- data/lib/util/log_analytics.rb +154 -0
- data/lib/util/logging.rb +96 -0
- data/lib/util/oci_clients.rb +228 -0
- data/lib/util/state_manager.rb +61 -0
- data/lib/util/string_utils.rb +16 -0
- data/lib/version.rb +6 -0
- data/oci-logging-analytics-kubernetes-discovery.gemspec +45 -0
- 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
|