oci-logging-analytics-kubernetes-discovery 1.0.3 → 1.1.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.
@@ -8,24 +8,27 @@ module Dto
8
8
  include Enum::KubernetesObjectsEnum
9
9
  extend Util::Logging
10
10
 
11
- attr_accessor :cluster, :nodes, :pods, :services, :endPointSlices, :deployments,
12
- :replicaSets, :daemonSets, :cronJobs, :jobs, :statefulSets, :events, :namespaces
11
+ attr_accessor :cluster, :nodes, :pods, :services, :endpointslices, :deployments,
12
+ :replicasets, :daemonsets, :cronjobs, :jobs, :statefulsets, :events, :namespaces,
13
+ :infra
13
14
 
14
- def initialize(cluster, nodes, pods, services, endPointSlices, deployments,
15
- replicaSets, daemonSets, cronJobs, jobs, statefulSets, events, namespaces)
15
+ def initialize(cluster, nodes, pods, services, endpointslices, deployments,
16
+ replicasets, daemonsets, cronjobs, jobs, statefulsets, events, namespaces,
17
+ infra)
16
18
  @cluster = cluster
17
19
  @nodes = nodes
18
20
  @pods = pods
19
21
  @services = services
20
- @endPointSlices = endPointSlices
22
+ @endpointslices = endpointslices
21
23
  @deployments = deployments
22
- @replicaSets = replicaSets
23
- @daemonSets = daemonSets
24
- @cronJobs = cronJobs
24
+ @replicasets = replicasets
25
+ @daemonsets = daemonsets
26
+ @cronjobs = cronjobs
25
27
  @jobs = jobs
26
- @statefulSets = statefulSets
28
+ @statefulsets = statefulsets
27
29
  @events = events
28
30
  @namespaces = namespaces
31
+ @infra = infra
29
32
  end
30
33
 
31
34
  def get_hash(obj, obj_name)
@@ -43,15 +46,16 @@ module Dto
43
46
  nodes: get_hash(@nodes, NODES.to_s),
44
47
  pods: get_hash(@pods, PODS.to_s),
45
48
  services: get_hash(@services, SERVICES.to_s),
46
- endpointslices: get_hash(@endPointSlices, ENDPOINT_SLICES.to_s),
49
+ endpointslices: get_hash(@endpointslices, ENDPOINT_SLICES.to_s),
47
50
  deployments: get_hash(@deployments, DEPLOYMENTS.to_s),
48
- replicasets: get_hash(@replicaSets, REPLICA_SETS.to_s),
49
- daemonsets: get_hash(@daemonSets, DAEMON_SETS.to_s),
50
- cronjobs: get_hash(@cronJobs, CRON_JOBS.to_s),
51
+ replicasets: get_hash(@replicasets, REPLICA_SETS.to_s),
52
+ daemonsets: get_hash(@daemonsets, DAEMON_SETS.to_s),
53
+ cronjobs: get_hash(@cronjobs, CRON_JOBS.to_s),
51
54
  jobs: get_hash(@jobs, JOBS.to_s),
52
- statefulsets: get_hash(@statefulSets, STATEFUL_SETS.to_s),
55
+ statefulsets: get_hash(@statefulsets, STATEFUL_SETS.to_s),
53
56
  events: get_hash(@events, EVENTS.to_s),
54
- namespaces: get_hash(@namespaces, NAMESPACES.to_s)
57
+ namespaces: get_hash(@namespaces, NAMESPACES.to_s),
58
+ infra: @infra.nil? ? nil : @infra.to_hash
55
59
  }.compact
56
60
  end
57
61
  end
data/lib/dto/state.rb CHANGED
@@ -3,16 +3,20 @@
3
3
 
4
4
  module Dto
5
5
  class State
6
- attr_accessor :last_timestamp
6
+ attr_accessor :last_timestamp, :retry_eligible_resources, :svc_log_stack_id
7
7
 
8
- def initialize(last_timestamp = nil)
8
+ def initialize(last_timestamp = nil, retry_eligible_resources = nil, svc_log_stack_id = nil)
9
9
  @last_timestamp = last_timestamp unless last_timestamp.nil?
10
+ @retry_eligible_resources = retry_eligible_resources unless retry_eligible_resources.nil?
11
+ @svc_log_stack_id = svc_log_stack_id unless svc_log_stack_id.nil?
10
12
  end
11
13
 
12
14
  # make sure all values are strings
13
15
  def to_hash
14
16
  {
15
- last_timestamp: @last_timestamp.to_s
17
+ last_timestamp: @last_timestamp.to_s,
18
+ retry_eligible_resources: @retry_eligible_resources.to_s,
19
+ svc_log_stack_id: @svc_log_stack_id.to_s
16
20
  }.compact
17
21
  end
18
22
  end
@@ -5,5 +5,6 @@ module Enum
5
5
  module InfrastructureResourceDiscovery
6
6
  SUBNET = 'subnet'.freeze
7
7
  NODE_POOLS = 'node_pools'.freeze
8
+ LOAD_BALANCER = 'load_balancers'.freeze
8
9
  end
9
10
  end
@@ -2,7 +2,7 @@
2
2
  ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
3
3
 
4
4
  module Enum
5
- module ObjectClientMapingEnum
5
+ module ObjectClientMappingEnum
6
6
  NODES = :core_client
7
7
  PODS = :core_client
8
8
  SERVICES = :core_client
@@ -0,0 +1,14 @@
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 StackJobLifecycleStateEnum
6
+ # Documentation: https://docs.oracle.com/en-us/iaas/Content/ResourceManager/Tasks/jobs.htm
7
+ ACCEPTED = 'ACCEPTED'.freeze
8
+ IN_PROGRESS = 'IN_PROGRESS'.freeze
9
+ FAILED = 'FAILED'.freeze
10
+ SUCCEEDED = 'SUCCEEDED'.freeze
11
+ CANCELING = 'CANCELING'.freeze
12
+ CANCELED = 'CANCELED'.freeze
13
+ end
14
+ end
@@ -0,0 +1,10 @@
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 StackJobOperationEnum
6
+ APPLY = 'APPLY'.freeze
7
+ PLAN = 'PLAN'.freeze
8
+ DESTROY = 'DESTROY'.freeze
9
+ end
10
+ end
@@ -1,6 +1,8 @@
1
1
  ## Copyright (c) 2024 Oracle and/or its affiliates.
2
2
  ## The Universal Permissive License (UPL), Version 1.0 as shown at https://oss.oracle.com/licenses/upl/
3
3
 
4
+ require 'set'
5
+
4
6
  # Infra
5
7
  require_relative './discover/infrastructure'
6
8
 
@@ -8,11 +10,10 @@ require_relative './discover/infrastructure'
8
10
  require_relative './dto/infra_objects_payload'
9
11
 
10
12
  # 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'
13
+ require_relative './dto/infra/resource_payload'
14
+ require_relative './dto/infra/subnet_payload'
15
+ require_relative './dto/infra/node_pool_payload'
16
+ require_relative './dto/infra/load_balancer_payload'
16
17
 
17
18
  # Util
18
19
  require_relative './util/logging'
@@ -23,66 +24,166 @@ module InfraResources
23
24
 
24
25
  module_function
25
26
 
26
- def get_infra_resources(auth_object, cluster_id)
27
+ IP_Address = Struct.new(:ip, :isPublic)
28
+ Nodes = Struct.new(:id, :name, :subnetId, :privateIp, :publicIp, :lifecycleState)
29
+
30
+ def get_infra_resources(app_config, cluster_config, cluster_id, lb_ip_array)
31
+
27
32
  # Fetch cluster details using cluster OCID provided as argument during program run
28
33
  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)
34
+ ce_response = Discover::Infrastructure.fetch_cluster_details(cluster_id)
35
+ cluster_details = Dto::Infra::ResourcePayload.new(ce_response.name, ce_response.id, ce_response.compartment_id)
31
36
 
32
37
  # Fetch VCN associated with cluster
33
38
  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)
39
+ vcn_response = Discover::Infrastructure.fetch_vcn_response(ce_response.vcn_id)
40
+ vcn_details = Dto::Infra::ResourcePayload.new(vcn_response.display_name, vcn_response.id, vcn_response.compartment_id)
36
41
 
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)
42
+ # Use resource search query to fetch load balancers associated with cluster OCID
43
+ logger.debug('Fetching load balancers associated with cluster.')
40
44
 
41
- # Loop subnet response to get individual subnets.
42
- subnet_entity_payload = []
43
- subnet_response.each do |subnet|
44
- next if subnet.nil?
45
+ load_balancer_details = []
45
46
 
46
- subnet_entity_payload.push(Dto::Infra::SubnetEntityPayload.new(subnet.display_name, subnet.id))
47
- end
47
+ lb_ip_array.each do |ip|
48
+ structured_query = "query loadbalancer resources matching '#{ip}'"
48
49
 
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)
50
+ resource_query_search_response = Discover::Infrastructure.search_with_structured_query(structured_query)
51
+
52
+ # TODO: We only expect one LB per IP address, remove looping over result ?
52
53
 
53
- load_balancer_entity_payload = nil
54
- free_text_response.items.each do |item|
55
- next if item.nil?
54
+ # Load Balancer Lifecycle State: CREATING, ACTIVE, DELETING
55
+ resource_query_search_response.items.each do |item|
56
+ lb_response = Discover::Infrastructure.fetch_load_balancer_details(item.identifier)
57
+ next if lb_response[:data].nil?
58
+ lb_ip_addresses = []
56
59
 
57
- next unless item.resource_type == 'LoadBalancer'
60
+ lb_response[:data].ip_addresses.each do |item|
61
+ lb_ip_addresses.push(IP_Address.new(item.ip_address, item.is_public))
62
+ end
58
63
 
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
+ subnet_ids = lb_response[:data].subnet_ids.nil? ? [] : lb_response[:data].subnet_ids
65
+
66
+ load_balancer_details.push(Dto::Infra::LoadBalancerPayload.new(lb_response[:data].display_name,
67
+ lb_response[:data].id,
68
+ lb_response[:data].compartment_id,
69
+ lb_response[:data].is_private,
70
+ lb_ip_addresses,
71
+ lb_response[:data].lifecycle_state,
72
+ subnet_ids))
73
+
74
+ logger.debug("LB detected : #{lb_response}")
64
75
  end
65
76
  end
66
77
 
78
+ logger.info("Discovered load balancer count: #{load_balancer_details.length}")
79
+
67
80
  # Iterate through all the compartments (starting from root tenancy level) and fetch node pools
68
81
  # 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?
82
+ node_pool_details = []
83
+ node_pool_subnet_ids = []
84
+ worker_node_subnet_ids = []
85
+
86
+ logger.debug('Fetching node pools associated with cluster.')
87
+
88
+ node_pool_compartment_id = nil
89
+ scoped_at_tenancy = false
90
+ if app_config[:probe_all_compartments]
91
+ # Tenancy OCID is compulsory input if probe_all_compartments flag is set
92
+ logger.info('Node pool discovery scope set at tenancy level.')
93
+
94
+ node_pool_compartment_id = app_config[:tenancy_ocid]
95
+ scoped_at_tenancy = true
96
+ else
97
+ logger.info('Node pool discovery scoped to cluster compartment.')
98
+ node_pool_compartment_id = ce_response.compartment_id
99
+ end
100
+
101
+ begin
102
+ compartment_list_response = Discover::Infrastructure.fetch_compartment_list(node_pool_compartment_id, scoped_at_tenancy)
103
+ rescue StandardError => e
104
+ logger.error("Error while fetching compartment list. Error: [#{e}]")
105
+ raise StandardError, 'Error while fetching compartment list.'
106
+ end
107
+
108
+ compartment_list = []
109
+ compartment_list_response[:data]&.each do |compartment|
110
+ compartment_list.push(compartment.id)
111
+ end
112
+
113
+ if scoped_at_tenancy
114
+ compartment_list.push(app_config[:tenancy_ocid])
115
+ else
116
+ compartment_list.push(ce_response.compartment_id)
117
+ end
118
+
119
+ compartment_list.each do |compartment|
120
+
121
+ node_pool_list_response = Discover::Infrastructure.fetch_node_pool_lists(compartment, ce_response.id)
122
+
123
+ node_pool_list_response.each do |node_pool|
124
+
125
+ subnet_ids = node_pool.subnet_ids.nil? ? [] : node_pool.subnet_ids
126
+
127
+ subnet_ids.each do |node_pool_subnet|
128
+ node_pool_subnet_ids.push(node_pool_subnet)
129
+ end
130
+
131
+ node_pool_response = Discover::Infrastructure.fetch_node_pool(node_pool.id)
132
+
133
+ nodes = []
134
+ node_pool_response&.nodes&.each do |node_instance|
135
+ nodes.push(Nodes.new(node_instance.id, node_instance.name, node_instance&.subnet_id,
136
+ node_instance&.private_ip, node_instance&.public_ip, node_instance.lifecycle_state))
137
+ end
138
+
139
+ node_pool_details.push(Dto::Infra::NodePoolPayload.new(node_pool.name, node_pool.id,
140
+ node_pool.compartment_id, subnet_ids, nodes))
141
+
142
+ # Fetch worker node subnet details from placement configurations
143
+ placement_configs_details = node_pool.node_config_details.placement_configs
144
+ placement_configs_details.each do |placement_config|
145
+ next if placement_config.nil?
146
+
147
+ worker_node_subnet_ids.push(placement_config.subnet_id)
148
+ end
149
+ end
150
+ end
151
+
152
+ # Fetch details of subnets associated with cluster
153
+ # Subnet Lifecycle State: AVAILABLE, PROVISIONING, TERMINATED, TERMINATING, UPDATING
154
+ logger.debug('Fetching subnet details associated with cluster.')
155
+
156
+ subnet_resource_details = []
157
+ cluster_subnet_ids = []
158
+
159
+ kubernetes_api_endpoint_subnet_id = ce_response.endpoint_config.subnet_id
160
+ service_loadbalancer_subnet_ids = ce_response.options.service_lb_subnet_ids
161
+
162
+ cluster_subnet_ids.push(kubernetes_api_endpoint_subnet_id)
163
+ cluster_subnet_ids += service_loadbalancer_subnet_ids
164
+ cluster_subnet_ids += node_pool_subnet_ids
165
+ cluster_subnet_ids += worker_node_subnet_ids
166
+
167
+ # Remove duplicates. The | operator is used to compute the union of two arrays
168
+ # and ensures there are no duplicates. Adding the union of an array with [] does
169
+ # not change the original array but removes the duplicates
170
+ cluster_subnet_ids = cluster_subnet_ids | []
73
171
 
74
- node_pool_response = Discover::Infrastructure.fetch_node_pool_lists(auth_object, compartment.id, ce_response.id)
172
+ cluster_subnet_ids.each do |subnet_id|
75
173
 
76
- node_pool_response.each do |node_pool|
77
- next if node_pool.nil?
174
+ subnet_details = Discover::Infrastructure.fetch_subnet_details(subnet_id)
78
175
 
79
- node_pool_entity_payload.push(Dto::Infra::NodePoolEntityPayload.new(node_pool.node_image_name, node_pool.node_image_id, node_pool.compartment_id))
176
+ if !subnet_details[:data].nil? && subnet_details[:status] == 200
177
+ subnet = subnet_details[:data]
178
+ subnet_resource_details.push(Dto::Infra::SubnetPayload.new(subnet.display_name, subnet.id, subnet.compartment_id,
179
+ subnet.prohibit_internet_ingress, subnet.prohibit_public_ip_on_vnic,
180
+ subnet.cidr_block, subnet.lifecycle_state))
80
181
  end
81
182
  end
82
183
 
83
184
  Dto::InfraObjectsPayLoad.new(
84
- cluster_entity_payload, vcn_entity_payload, subnet_entity_payload,
85
- load_balancer_entity_payload, node_pool_entity_payload
185
+ cluster_details, vcn_details, subnet_resource_details,
186
+ load_balancer_details, node_pool_details
86
187
  )
87
188
  rescue StandardError => e
88
189
  logger.error("Error in getting infrastructure resources: #{e}")
@@ -56,7 +56,7 @@ module ObjectsResources
56
56
 
57
57
  begin
58
58
  payload_executors = Enum::KubernetesObjectsEnum.constants(false).map do |object_type|
59
- if Enum::ObjectClientMapingEnum.const_defined? object_type
59
+ if Enum::ObjectClientMappingEnum.const_defined? object_type
60
60
  if enable_threading == true
61
61
  Concurrent::Future.execute({ executor: thread_pool }) do
62
62
  get_objects_resources(object_type)
@@ -80,11 +80,21 @@ module ObjectsResources
80
80
  end_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
81
81
  logger.debug("Time elapsed in collecting objects: #{(end_time - start_time).round(2)} seconds.")
82
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
- )
83
+ kubernetes_objects_processed = {
84
+ cluster: cluster,
85
+ nodes: @nodes[:processed],
86
+ pods: @pods[:processed],
87
+ services: @services[:processed],
88
+ endpoint_slices: @endpoint_slices[:processed],
89
+ deployments: @deployments[:processed],
90
+ replica_sets: @replica_sets[:processed],
91
+ daemon_sets: @daemon_sets[:processed],
92
+ cron_jobs: @cron_jobs[:processed],
93
+ jobs: @jobs[:processed],
94
+ stateful_sets: @stateful_sets[:processed],
95
+ events: @events[:processed],
96
+ namespaces: @namespaces[:processed]
97
+ }
88
98
 
89
99
  kubernetes_objects_raw_responses = {
90
100
  nodes: @nodes[:raw],
@@ -16,6 +16,7 @@ require_relative './util/kube_client'
16
16
  require_relative './util/oci_clients'
17
17
  require_relative './util/log_analytics'
18
18
  require_relative './util/state_manager'
19
+ require_relative './util/service_logs'
19
20
 
20
21
  # DTO
21
22
  require_relative './dto/payload/log_events'
@@ -39,7 +40,7 @@ module OciLogAnalyticsResourcesDiscovery
39
40
  module_function
40
41
 
41
42
  attr_accessor :cluster_config_hash, :auth_config_hash, :kube_config_hash, :app_config_hash,
42
- :auth_object, :kube_clients, :oci_clients, :snapshot_id
43
+ :auth_object, :kube_clients, :oci_clients, :oci_region, :oci_domain, :snapshot_id
43
44
 
44
45
  @@oci_la_log_source_name = 'Kubernetes Objects Discovery Payload Logs'
45
46
  @@oci_la_log_path = 'UNDEFINED'
@@ -49,59 +50,78 @@ module OciLogAnalyticsResourcesDiscovery
49
50
  @auth_config_hash = auth_config_hash
50
51
  @kube_config_hash = kube_config_hash
51
52
  @app_config_hash = app_config_hash
53
+ end
52
54
 
53
- # OCI.logger = Util::Logging.logger
54
-
55
- options = { mode: app_config_hash[:mode] }
56
- Util::OCIClients.initialize(@auth_config_hash, options)
55
+ def initiate_discovery
56
+ Util::OCIClients.initialize(@auth_config_hash)
57
57
 
58
58
  @auth_object = Util::OCIClients.get_auth_config_object
59
59
  @oci_clients = Util::OCIClients.get_clients
60
+ @oci_region = Util::OCIClients.get_region
61
+ @oci_domain = Util::OCIClients.get_domain
60
62
 
61
- if @app_config_hash[:mode] == 'object'
62
- @snapshot_id = Time.now.to_i
63
- get_kube_clients
64
- Util::StateManager.init(@cluster_config_hash[:kubernetes_resourcename_prefix], @cluster_config_hash[:kubernetes_cluster_namespace])
65
- Util::KubectlOps.set_chunk_limit @app_config_hash[:chunk_limit]
66
- logger.debug("Chunk limit set to - #{@app_config_hash[:chunk_limit]}")
67
- end
68
- end
63
+ @kube_clients = Util::KubeClient.create_clients(@kube_config_hash)
69
64
 
70
- def initiate_infra_discovery
71
- logger.info('Initiating Kubernetes infrastructure discovery.')
72
- begin
73
- infra_objects_payload = get_infra_resources_payload
74
- rescue StandardError => e
75
- logger.error("Error occurred while fetching infrastructure resources. Error: #{e}")
76
- raise StandardError, 'Error occurred while fetching infrastructure resources.'
77
- end
65
+ Util::StateManager.init(@cluster_config_hash[:kubernetes_resourcename_prefix], @cluster_config_hash[:kubernetes_cluster_namespace])
78
66
 
79
- logger.info('Infrastructure discovery payload created.')
80
- logger.trace("Infrastructure discovery payload: \n#{Yajl.dump(infra_objects_payload.to_hash)}")
67
+ # Collect infrastructure discovery data
68
+ infra_objects_payload = nil
69
+ infra_discovery_failed = false
81
70
 
82
- if @app_config_hash[:skip_upload]
83
- logger.warn('--skip_upload Flag is set: Skipping payload upload to OCI Logging Analytics.')
84
- else
85
- if !infra_objects_payload.nil?
86
- # TODO: Upload implemetation pending.
87
- else
88
- logger.warn('No infrastructure objects discovered.')
89
- end
90
- end
91
- end
71
+ logger.info('Initiating Kubernetes Objects discovery.')
72
+
73
+ # Collect platform discovery data
74
+ @snapshot_id = Time.now.to_i
75
+ Util::KubectlOps.set_chunk_limit @app_config_hash[:chunk_limit]
76
+ logger.debug("Chunk limit set to - #{@app_config_hash[:chunk_limit]}")
92
77
 
93
- def initiate_object_discovery
94
78
  kubernetes_objects_payload = get_objects_resources_payload
79
+
95
80
  if @app_config_hash[:collect_warning_events_only]
96
81
  logger.info('Only Warning event logs will be collected as the following flag is set: --collect_warning_events_only')
97
82
  end
83
+
98
84
  kubernetes_objects_payload = filter_event_logs(kubernetes_objects_payload,
99
85
  @app_config_hash[:collect_warning_events_only])
100
86
 
101
87
  logger.info('Kubernetes objects discovery payload created.')
102
- logger.trace("Object Discovery Payload: \n#{Yajl.dump(kubernetes_objects_payload[:processed_objects].to_hash)}")
103
88
  logger.trace("Object Log Collection Payload: \n#{Yajl.dump(kubernetes_objects_payload[:raw_response].to_hash)}")
104
89
 
90
+ if @cluster_config_hash[:enable_infra_discovery]
91
+ logger.info('Initiating kubernetes infrastructure discovery.')
92
+ begin
93
+ lb_ip_array = parse_lb_ips(kubernetes_objects_payload)
94
+ logger.info("Discovered Load Balancer IPs: #{lb_ip_array}")
95
+ infra_objects_payload = InfraResources.get_infra_resources(
96
+ @app_config_hash,
97
+ @cluster_config_hash,
98
+ @cluster_config_hash[:kubernetes_cluster_id],
99
+ lb_ip_array
100
+ )
101
+ logger.trace("Infrastructure discovery payload: \n#{Yajl.dump(infra_objects_payload.to_hash)}")
102
+ logger.info('Infrastructure discovery payload created.')
103
+ rescue StandardError => e
104
+ # Not raising an error as platform discovery still needs to continue.
105
+ infra_discovery_failed = true
106
+ logger.error("Error occurred while fetching infrastructure resources. Error: #{e}")
107
+ logger.info('Proceeding with object discovery.')
108
+ end
109
+ else
110
+ logger.info('--kubernetes_cluster_id not provided. Infrastructure discovery skipped.') # TODO: should be Warn ?
111
+ end
112
+
113
+ # Combine discovery and infrastructure data
114
+ processed_objects = kubernetes_objects_payload[:processed_objects]
115
+ combined_data = Dto::KubernetesObjectsPayLoad.new(
116
+ processed_objects[:cluster], processed_objects[:nodes], processed_objects[:pods], processed_objects[:services], processed_objects[:endpoint_slices],
117
+ processed_objects[:deployments], processed_objects[:replica_sets], processed_objects[:daemon_sets], processed_objects[:cron_jobs],
118
+ processed_objects[:jobs], processed_objects[:stateful_sets], processed_objects[:events], processed_objects[:namespaces], infra_objects_payload
119
+ )
120
+
121
+ logger.info('Combined discovery payload created.')
122
+ logger.trace("Combined discovery payload: \n#{Yajl.dump(combined_data.to_hash)}")
123
+
124
+ # Send collected data
105
125
  if @app_config_hash[:skip_upload]
106
126
  logger.warn('--skip_upload Flag is set: Skipping payload upload to OCI logging analytics.')
107
127
  else
@@ -119,7 +139,8 @@ module OciLogAnalyticsResourcesDiscovery
119
139
  upload_data_via_discovery_api(zip_object_log_payload, object_logs_opts) unless zip_object_log_payload.nil?
120
140
  logger.info('Successfully uploaded object logs to OCI')
121
141
 
122
- # Update the Events tracker config map only after successful objects logs upload
142
+ # DEV NOTE: Update the Events tracker config map only after successful objects logs upload
143
+ # Carefully check how last_timestamp update is managed if you wish to move the below code
123
144
  Util::StateManager.update_state_configmap
124
145
  rescue StandardError
125
146
  logger.error('Error occurred while uploading object logs to OCI')
@@ -129,22 +150,53 @@ module OciLogAnalyticsResourcesDiscovery
129
150
  unless @cluster_config_hash[:oci_la_cluster_entity_id].nil?
130
151
  begin
131
152
  # Upload object discovery payload with relevant header parameters
132
- logger.info('Uploading Object Discovery Payload to OCI')
153
+ logger.info('Uploading Discovery Payload to OCI')
133
154
  object_discovery_opts = {
134
155
  payload_type: 'JSON',
135
156
  discovery_data_type: 'K8S_OBJECTS',
136
157
  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]}"
137
158
  }
138
- json_object_discovery_payload = Yajl.dump(kubernetes_objects_payload[:processed_objects].to_hash)
159
+ json_object_discovery_payload = Yajl.dump(combined_data.to_hash)
139
160
  upload_data_via_discovery_api(json_object_discovery_payload, object_discovery_opts)
140
- logger.info('Successfully uploaded object discovery payload to OCI')
161
+ logger.info('Successfully uploaded discovery payload to OCI')
141
162
  rescue StandardError
142
- logger.error('Error occurred while uploading object discovery payload to OCI')
163
+ logger.error('Error occurred while uploading discovery payload to OCI')
143
164
  upload_failure = true
144
165
  end
145
166
  end
146
167
 
147
- raise StandardError, 'Error occurred while uploading payloads to OCI' if upload_failure
168
+ raise StandardError, 'Error uploading payloads to OCI' if upload_failure
169
+ end
170
+
171
+ # Execute Resource Manager Stack
172
+ if !infra_discovery_failed && @app_config_hash[:enable_service_log]
173
+ logger.info('Initiating service logs collection.')
174
+ log_analytics_entity_details = nil
175
+ begin
176
+ log_analytics_entity_details = Util::ServiceLogs.fetch_log_analytics_entity_details(
177
+ @cluster_config_hash[:oci_la_namespace],
178
+ @cluster_config_hash[:oci_la_cluster_entity_id]
179
+ )
180
+ rescue StandardError => e
181
+ logger.error('Error fetching log analytics entity details.')
182
+ end
183
+ unless log_analytics_entity_details.nil?
184
+ begin
185
+ logger.info('Invoking resource manager stack for service log creation')
186
+ Util::ServiceLogs.invoke_resource_manager_stack(infra_objects_payload,
187
+ @app_config_hash,
188
+ @cluster_config_hash[:oci_la_log_group_id],
189
+ log_analytics_entity_details.compartment_id,
190
+ @oci_region,
191
+ @oci_domain)
192
+ rescue StandardError => e
193
+ logger.error('Error invoking/updating service logs collection')
194
+ raise e
195
+ end
196
+ end
197
+ else
198
+ log_msg = infra_discovery_failed ? 'No infrastructure objects discovered' : 'Flag --enable_service_log not provided'
199
+ logger.info("#{log_msg}. Stack operations skipped")
148
200
  end
149
201
  end
150
202
 
@@ -155,22 +207,9 @@ module OciLogAnalyticsResourcesDiscovery
155
207
  logger.error("Error occurred in creating kubeclients - #{e}")
156
208
  raise e
157
209
  end
158
- @kube_clients = Util::KubeClient.get_clients
159
- logger.debug('Kubeclients created successfully.')
160
- end
161
-
162
- def get_infra_resources_payload
163
- logger.debug('Discovering Infrastructure Resources')
164
- infra_resources_payload = nil
165
-
166
- unless @auth_object.nil?
167
- begin
168
- infra_resources_payload = InfraResources.get_infra_resources(@auth_object, @cluster_config_hash[:oci_la_cluster_entity_id])
169
- rescue StandardError => e
170
- logger.error("Error in getting infrastructure resources: #{e}")
171
- end
172
- end
173
- infra_resources_payload
210
+ @kube_clients =
211
+ logger.debug('Kube client created successfully.')
212
+ Util::KubeClient.get_clients
174
213
  end
175
214
 
176
215
  def get_objects_resources_payload
@@ -184,6 +223,15 @@ module OciLogAnalyticsResourcesDiscovery
184
223
  )
185
224
  end
186
225
 
226
+ def parse_lb_ips(kubernetes_objects_payload)
227
+ ip_array = []
228
+ lbs = kubernetes_objects_payload[:processed_objects][:services].select { |service| service[:serviceType] == "LoadBalancer" }
229
+ lbs.each do |lb|
230
+ ip_array.append lb.loadBalancerIP unless lb.loadBalancerIP.nil?
231
+ end
232
+ ip_array
233
+ end
234
+
187
235
  def filter_event_logs(kubernetes_objects_payload, collect_warning_events_only)
188
236
  cluster_events_processed_time = Util::StateManager.state.last_timestamp
189
237
  new_processed_time = cluster_events_processed_time
@@ -27,6 +27,7 @@ module Util
27
27
  raise e
28
28
  end
29
29
 
30
+ logger.debug('Kube clients created successfully.')
30
31
  set_clients(@core_client, @apps_client, @batch_client, @discover_v1_client)
31
32
  end
32
33
 
@@ -48,7 +48,7 @@ module Util
48
48
  case method
49
49
  when :get_objects
50
50
  if client.nil?
51
- client = Util::KubeClient.get_clients[Enum::ObjectClientMapingEnum.const_get(object_type.upcase.to_s)]
51
+ client = Util::KubeClient.get_clients[Enum::ObjectClientMappingEnum.const_get(object_type.upcase.to_s)]
52
52
  end
53
53
  logger.debug("Fetching '#{object_type}' details from all namespaces")
54
54
  method_verb = 'GET'