Skip to content

Commit

Permalink
Merge pull request #30 from agrare/add_oke_container_manager
Browse files Browse the repository at this point in the history
Add OKE oracle_cloud container_manager

(cherry picked from commit 8b23926)
  • Loading branch information
Fryguy committed Sep 10, 2021
1 parent efe8c8c commit 1e62bcc
Show file tree
Hide file tree
Showing 36 changed files with 1,300 additions and 88 deletions.
59 changes: 51 additions & 8 deletions app/models/manageiq/providers/oracle_cloud/cloud_manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,52 @@ class ManageIQ::Providers::OracleCloud::CloudManager < ManageIQ::Providers::Clou
require_nested :Template
require_nested :Vm

include ManageIQ::Providers::OracleCloud::ManagerMixin
include ManageIQ::Providers::OracleCloud::OciConnectMixin

supports :regions

before_create :ensure_managers
before_update :ensure_managers_zone_and_provider_region

validates :provider_region, :inclusion => {:in => ManageIQ::Providers::OracleCloud::Regions.names}

def ensure_network_manager
build_network_manager(:type => 'ManageIQ::Providers::OracleCloud::NetworkManager') unless network_manager
end

def connect(options = {})
auth_type = options.delete(:auth_type)

authentication = authentication_best_fit(auth_type)
config = self.class.raw_connect(
uid_ems,
authentication.userid,
authentication.auth_key,
authentication.public_key,
provider_region
)

service = options.delete(:service)
if service
api_client_klass = "OCI::#{service}".safe_constantize
raise ArgumentError, _("Invalid service") if api_client_klass.nil?

api_client_klass.new(options.reverse_merge(:config => config))
else
config
end
end

def verify_credentials(auth_type = nil, _options = {})
begin
connect(:service => "Identity::IdentityClient").get_user(authentication_userid(auth_type))
rescue => err
raise MiqException::MiqInvalidCredentialsError, err.message
end

true
end

def self.hostname_required?
false
end
Expand All @@ -46,7 +81,7 @@ def self.params_for_create
:isRequired => true,
:validate => [{:type => "required"}],
:includeEmpty => true,
:options => provider_region_options
:options => ManageIQ::Providers::OracleCloud::Regions.regions_for_options
},
{
:component => "text-field",
Expand Down Expand Up @@ -107,14 +142,22 @@ def self.params_for_create
}
end

private_class_method def self.provider_region_options
ManageIQ::Providers::OracleCloud::Regions
.all
.sort_by { |r| r[:name].downcase }
.map { |r| {:label => r[:name], :value => r[:name]} }
def self.verify_credentials(args)
region, tenant = args.values_at("provider_region", "uid_ems")

default_endpoint = args.dig("authentications", "default")
user, private_key, public_key = default_endpoint&.values_at("userid", "auth_key", "public_key")

private_key ||= find(args["id"]).authentication_token("default")

config = raw_connect(tenant, user, private_key, public_key, region)
identity_api = OCI::Identity::IdentityClient.new(:config => config)
!!identity_api.get_user(user)
end

validates :provider_region, :inclusion => {:in => ManageIQ::Providers::OracleCloud::Regions.names}
def self.raw_connect(tenant, user, private_key, public_key, region)
oci_config(tenant, user, private_key, public_key, region)
end

def allow_targeted_refresh?
true
Expand Down
232 changes: 232 additions & 0 deletions app/models/manageiq/providers/oracle_cloud/container_manager.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
ManageIQ::Providers::Kubernetes::ContainerManager.include(ActsAsStiLeafClass)

class ManageIQ::Providers::OracleCloud::ContainerManager < ManageIQ::Providers::Kubernetes::ContainerManager
require_nested :Container
require_nested :ContainerGroup
require_nested :ContainerNode
require_nested :EventCatcher
require_nested :EventParser
require_nested :Refresher
require_nested :RefreshWorker

include ManageIQ::Providers::OracleCloud::OciConnectMixin

validates :provider_region, :inclusion => {:in => ManageIQ::Providers::OracleCloud::Regions.names}

def connect_options(options = {})
authentication = authentication_best_fit(options.fetch(:auth_type, "bearer"))

super.merge(
:tenant => realm,
:user => authentication.userid,
:private_key => authentication.auth_key,
:public_key => authentication.public_key,
:region => provider_region,
:cluster_id => uid_ems
)
end

class << self
def ems_type
@ems_type ||= "oke".freeze
end

def description
@description ||= "Oracle Kubernetes Engine".freeze
end

def display_name(number = 1)
n_('Container Provider (Oracle)', 'Container Providers (Oracle)', number)
end

def default_port
6443
end

def kubernetes_auth_options(options)
{
:bearer_token => bearer_token(*options.values_at(:tenant, :user, :private_key, :public_key, :region, :cluster_id))
}
end

def params_for_create
{
:fields => [
{
:component => "select",
:id => "provider_region",
:name => "provider_region",
:label => _("Region"),
:isRequired => true,
:validate => [{:type => "required"}],
:includeEmpty => true,
:options => ManageIQ::Providers::OracleCloud::Regions.regions_for_options
},
{
:component => "text-field",
:id => "realm",
:name => "realm",
:label => _("Tenant ID"),
:isRequired => true,
:validate => [{:type => "required"}]
},
{
:component => "text-field",
:id => "uid_ems",
:name => "uid_ems",
:label => _("Cluster ID"),
:isRequired => true,
:validate => [{:type => "required"}]
},
{
:component => 'sub-form',
:name => 'endpoints-subform',
:id => 'endpoints-subform',
:title => _("Endpoints"),
:fields => [
{
:component => 'validate-provider-credentials',
:id => 'authentications.bearer.valid',
:name => 'authentications.bearer.valid',
:skipSubmit => true,
:isRequired => true,
:validationDependencies => %w[type zone_id provider_region realm uid_ems],
:fields => [
{
:component => "select",
:id => "endpoints.default.security_protocol",
:name => "endpoints.default.security_protocol",
:label => _("Security Protocol"),
:isRequired => true,
:validate => [{:type => "required"}],
:initialValue => 'ssl-with-validation',
:options => [
{
:label => _("SSL"),
:value => "ssl-with-validation"
},
{
:label => _("SSL trusting custom CA"),
:value => "ssl-with-validation-custom-ca"
},
{
:label => _("SSL without validation"),
:value => "ssl-without-validation",
},
]
},
{
:component => "text-field",
:id => "endpoints.default.hostname",
:name => "endpoints.default.hostname",
:label => _("Hostname (or IPv4 or IPv6 address)"),
:isRequired => true,
:validate => [{:type => "required"}],
},
{
:component => "text-field",
:id => "endpoints.default.port",
:name => "endpoints.default.port",
:label => _("API Port"),
:type => "number",
:initialValue => default_port,
:isRequired => true,
:validate => [{:type => "required"}],
},
{
:component => "textarea",
:id => "endpoints.default.certificate_authority",
:name => "endpoints.default.certificate_authority",
:label => _("Trusted CA Certificates"),
:rows => 10,
:isRequired => true,
:validate => [{:type => "required"}],
:condition => {
:when => 'endpoints.default.security_protocol',
:is => 'ssl-with-validation-custom-ca',
},
},
{
:component => "text-field",
:id => "authentications.bearer.userid",
:name => "authentications.bearer.userid",
:label => _("User ID"),
:helperText => _("Should have privileged access, such as root or administrator."),
:isRequired => true,
:validate => [{:type => "required"}]
},
{
:component => "password-field",
:componentClass => 'textarea',
:rows => 10,
:id => "authentications.bearer.auth_key",
:name => "authentications.bearer.auth_key",
:label => _("Private Key"),
:type => "password",
:isRequired => true,
:validate => [{:type => "required"}]
},
{
:component => "textarea",
:rows => 10,
:id => "authentications.bearer.public_key",
:name => "authentications.bearer.public_key",
:label => "Public Key",
:isRequired => true,
:validate => [{:type => "required"}]
}
],
},
]
}
]
}
end

def verify_credentials(args)
region, tenant, cluster_id = args.values_at("provider_region", "realm", "uid_ems")

default_endpoint = args.dig("endpoints", "default")
hostname, port, security_protocol, certificate_authority = default_endpoint&.values_at("hostname", "port", "security_protocol", "certificate_authority")

default_authentication = args.dig("authentications", "bearer")
user, private_key, public_key = default_authentication&.values_at("userid", "auth_key", "public_key")
private_key ||= find(args["id"]).authentication_token("default")

options = {
:tenant => tenant,
:user => user,
:private_key => private_key,
:public_key => public_key,
:region => region,
:cluster_id => cluster_id,
:ssl_options => {
:verify_ssl => security_protocol == "ssl-without-validation" ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER,
:certificate_authority => certificate_authority
}
}

!!raw_connect(hostname, port, options)
end

def bearer_token(tenant, user, private_key, public_key, region, cluster_id)
config = oci_config(tenant, user, private_key, public_key, region)
container_engine_client = OCI::ContainerEngine::ContainerEngineClient.new(:config => config)

# Prepare a signed request
signer = container_engine_client.api_client.instance_variable_get(:@signer)

url = URI::HTTPS.build(
:host => "containerengine.#{region}.oraclecloud.com",
:path => "/cluster_request/#{cluster_id}"
)

params = {}
signer.sign(:GET, url, params, nil)

url.query = params.to_query

Base64.urlsafe_encode64(url.to_s)
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ManageIQ::Providers::Kubernetes::ContainerManager::Container.include(ActsAsStiLeafClass)

class ManageIQ::Providers::OracleCloud::ContainerManager::Container < ManageIQ::Providers::Kubernetes::ContainerManager::Container
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ManageIQ::Providers::Kubernetes::ContainerManager::ContainerGroup.include(ActsAsStiLeafClass)

class ManageIQ::Providers::OracleCloud::ContainerManager::ContainerGroup < ManageIQ::Providers::Kubernetes::ContainerManager::ContainerGroup
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ManageIQ::Providers::Kubernetes::ContainerManager::ContainerNode.include(ActsAsStiLeafClass)

class ManageIQ::Providers::OracleCloud::ContainerManager::ContainerNode < ManageIQ::Providers::Kubernetes::ContainerManager::ContainerNode
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class ManageIQ::Providers::OracleCloud::ContainerManager::EventCatcher < ManageIQ::Providers::BaseManager::EventCatcher
require_nested :Runner

def self.settings_name
:event_catcher_oracle_oke
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class ManageIQ::Providers::OracleCloud::ContainerManager::EventCatcher::Runner < ManageIQ::Providers::BaseManager::EventCatcher::Runner
include ManageIQ::Providers::Kubernetes::ContainerManager::EventCatcherMixin
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ManageIQ::Providers::OracleCloud::ContainerManager::EventParser < ManageIQ::Providers::Kubernetes::ContainerManager::EventParser
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
class ManageIQ::Providers::OracleCloud::ContainerManager::RefreshWorker < ManageIQ::Providers::BaseManager::RefreshWorker
require_nested :Runner
require_nested :WatchThread

def self.settings_name
:ems_refresh_worker_oracle_oke
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ManageIQ::Providers::OracleCloud::ContainerManager::RefreshWorker::Runner < ManageIQ::Providers::Kubernetes::ContainerManager::RefreshWorker::Runner
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ManageIQ::Providers::OracleCloud::ContainerManager::RefreshWorker::WatchThread < ManageIQ::Providers::Kubernetes::ContainerManager::RefreshWorker::WatchThread
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module ManageIQ::Providers
module OracleCloud
class ContainerManager::Refresher < ManageIQ::Providers::BaseManager::Refresher
end
end
end
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class ManageIQ::Providers::OracleCloud::Inventory::Collector < ManageIQ::Providers::Inventory::Collector
require_nested :ContainerManager
require_nested :CloudManager
require_nested :NetworkManager
require_nested :TargetCollection
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class ManageIQ::Providers::OracleCloud::Inventory::Collector::ContainerManager < ManageIQ::Providers::Kubernetes::Inventory::Collector::ContainerManager
require_nested :WatchNotice

private

def kubernetes_connection
manager.connect
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
class ManageIQ::Providers::OracleCloud::Inventory::Collector::ContainerManager::WatchNotice < ManageIQ::Providers::Kubernetes::Inventory::Collector::ContainerManager::WatchNotice
end
Loading

0 comments on commit 1e62bcc

Please sign in to comment.