merged upstream master
This commit is contained in:
commit
ec6d48bb35
|
|
@ -17,4 +17,4 @@ name: cluster-autoscaler
|
|||
sources:
|
||||
- https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler
|
||||
type: application
|
||||
version: 9.11.0
|
||||
version: 9.13.1
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ Though enough for the majority of installations, the default PodSecurityPolicy _
|
|||
| azureResourceGroup | string | `""` | Azure resource group that the cluster is located. Required if `cloudProvider=azure` |
|
||||
| azureSubscriptionID | string | `""` | Azure subscription where the resources are located. Required if `cloudProvider=azure` |
|
||||
| azureTenantID | string | `""` | Azure tenant where the resources are located. Required if `cloudProvider=azure` |
|
||||
| azureUseManagedIdentityExtension | bool | `false` | Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID and resource group are set. |
|
||||
| azureUseManagedIdentityExtension | bool | `false` | Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID, resource group, and azure AKS cluster name are set. |
|
||||
| azureVMType | string | `"AKS"` | Azure VM type. |
|
||||
| cloudConfigPath | string | `"/etc/gce.conf"` | Configuration file for cloud provider. |
|
||||
| cloudProvider | string | `"aws"` | The cloud provider where the autoscaler runs. Currently only `gce`, `aws`, `azure` and `magnum` are supported. `aws` supported for AWS. `gce` for GCE. `azure` for Azure AKS. `magnum` for OpenStack Magnum. |
|
||||
|
|
@ -412,4 +412,5 @@ Though enough for the majority of installations, the default PodSecurityPolicy _
|
|||
| serviceMonitor.path | string | `"/metrics"` | The path to scrape for metrics; autoscaler exposes `/metrics` (this is standard) |
|
||||
| serviceMonitor.selector | object | `{"release":"prometheus-operator"}` | Default to kube-prometheus install (CoreOS recommended), but should be set according to Prometheus install. |
|
||||
| tolerations | list | `[]` | List of node taints to tolerate (requires Kubernetes >= 1.6). |
|
||||
| topologySpreadConstraints | list | `[]` | You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19). |
|
||||
| updateStrategy | object | `{}` | [Deployment update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy) |
|
||||
|
|
|
|||
|
|
@ -114,6 +114,11 @@ spec:
|
|||
secretKeyRef:
|
||||
key: VMType
|
||||
name: {{ template "cluster-autoscaler.fullname" . }}
|
||||
- name: AZURE_CLUSTER_NAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: ClusterName
|
||||
name: {{ template "cluster-autoscaler.fullname" . }}
|
||||
{{- if .Values.azureUseManagedIdentityExtension }}
|
||||
- name: ARM_USE_MANAGED_IDENTITY_EXTENSION
|
||||
value: "true"
|
||||
|
|
@ -133,11 +138,6 @@ spec:
|
|||
secretKeyRef:
|
||||
key: ClientSecret
|
||||
name: {{ template "cluster-autoscaler.fullname" . }}
|
||||
- name: AZURE_CLUSTER_NAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
key: ClusterName
|
||||
name: {{ template "cluster-autoscaler.fullname" . }}
|
||||
- name: AZURE_NODE_RESOURCE_GROUP
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
|
|
@ -218,6 +218,10 @@ spec:
|
|||
serviceAccountName: {{ template "cluster-autoscaler.serviceAccountName" . }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.tolerations | indent 8 }}
|
||||
{{- if .Values.topologySpreadConstraints }}
|
||||
topologySpreadConstraints:
|
||||
{{ toYaml .Values.topologySpreadConstraints | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.securityContext }}
|
||||
securityContext:
|
||||
{{ toYaml .Values.securityContext | nindent 8 | trim }}
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ azureClusterName: ""
|
|||
# Required if `cloudProvider=azure`
|
||||
azureNodeResourceGroup: ""
|
||||
|
||||
# azureUseManagedIdentityExtension -- Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID and resource group are set.
|
||||
# azureUseManagedIdentityExtension -- Whether to use Azure's managed identity extension for credentials. If using MSI, ensure subscription ID, resource group, and azure AKS cluster name are set.
|
||||
azureUseManagedIdentityExtension: false
|
||||
|
||||
# magnumClusterName -- Cluster name or ID in Magnum.
|
||||
|
|
@ -328,6 +328,15 @@ prometheusRule:
|
|||
# tolerations -- List of node taints to tolerate (requires Kubernetes >= 1.6).
|
||||
tolerations: []
|
||||
|
||||
# topologySpreadConstraints -- You can use topology spread constraints to control how Pods are spread across your cluster among failure-domains such as regions, zones, nodes, and other user-defined topology domains. (requires Kubernetes >= 1.19).
|
||||
topologySpreadConstraints: []
|
||||
# - maxSkew: 1
|
||||
# topologyKey: topology.kubernetes.io/zone
|
||||
# whenUnsatisfiable: DoNotSchedule
|
||||
# labelSelector:
|
||||
# matchLabels:
|
||||
# app.kubernetes.io/instance: cluster-autoscaler
|
||||
|
||||
# updateStrategy -- [Deployment update strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy)
|
||||
updateStrategy: {}
|
||||
# rollingUpdate:
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ You should also take a look at the notes and "gotchas" for your specific cloud p
|
|||
* [IonosCloud](./cloudprovider/ionoscloud/README.md)
|
||||
* [OVHcloud](./cloudprovider/ovhcloud/README.md)
|
||||
* [Linode](./cloudprovider/linode/README.md)
|
||||
* [OracleCloud](./cloudprovider/oci/README.md)
|
||||
* [ClusterAPI](./cloudprovider/clusterapi/README.md)
|
||||
* [BizflyCloud](./cloudprovider/bizflycloud/README.md)
|
||||
* [Vultr](./cloudprovider/vultr/README.md)
|
||||
|
|
@ -166,6 +167,7 @@ Supported cloud providers:
|
|||
* Equinix Metal https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/packet/README.md
|
||||
* OVHcloud https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/ovhcloud/README.md
|
||||
* Linode https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/linode/README.md
|
||||
* OCI https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/oci/README.md
|
||||
* Hetzner https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/hetzner/README.md
|
||||
* Cluster API https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/clusterapi/README.md
|
||||
* Vultr https://github.com/kubernetes/autoscaler/blob/master/cluster-autoscaler/cloudprovider/vultr/README.md
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/utils/clock"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ import (
|
|||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/util/clock"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
test_clock "k8s.io/utils/clock/testing"
|
||||
)
|
||||
|
||||
func TestInstanceTypeCache(t *testing.T) {
|
||||
|
|
@ -64,7 +64,7 @@ func TestLTVersionChange(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
fakeClock := clock.NewFakeClock(time.Unix(0, 0))
|
||||
fakeClock := test_clock.NewFakeClock(time.Unix(0, 0))
|
||||
fakeStore := cache.NewFakeExpirationStore(
|
||||
func(obj interface{}) (s string, e error) {
|
||||
return obj.(instanceTypeCachedObject).name, nil
|
||||
|
|
|
|||
|
|
@ -381,12 +381,16 @@ func overrideDefaultRateLimitConfig(defaults, config *azclients.RateLimitConfig)
|
|||
}
|
||||
|
||||
func (cfg *Config) getAzureClientConfig(authorizer autorest.Authorizer, env *azure.Environment) *azclients.ClientConfig {
|
||||
pollingDelay := 30 * time.Second
|
||||
azClientConfig := &azclients.ClientConfig{
|
||||
Location: cfg.Location,
|
||||
SubscriptionID: cfg.SubscriptionID,
|
||||
ResourceManagerEndpoint: env.ResourceManagerEndpoint,
|
||||
Authorizer: authorizer,
|
||||
Backoff: &retry.Backoff{Steps: 1},
|
||||
RestClientConfig: azclients.RestClientConfig{
|
||||
PollingDelay: &pollingDelay,
|
||||
},
|
||||
}
|
||||
|
||||
if cfg.CloudProviderBackoff {
|
||||
|
|
|
|||
|
|
@ -392,7 +392,7 @@ func (scaleSet *ScaleSet) DeleteInstances(instances []*azureRef, hasUnregistered
|
|||
|
||||
scaleSet.instanceMutex.Lock()
|
||||
klog.V(3).Infof("Calling virtualMachineScaleSetsClient.DeleteInstancesAsync(%v)", requiredIds.InstanceIds)
|
||||
future, rerr := scaleSet.manager.azClient.virtualMachineScaleSetsClient.DeleteInstancesAsync(ctx, resourceGroup, commonAsg.Id(), *requiredIds)
|
||||
future, rerr := scaleSet.manager.azClient.virtualMachineScaleSetsClient.DeleteInstancesAsync(ctx, resourceGroup, commonAsg.Id(), *requiredIds, false)
|
||||
scaleSet.instanceMutex.Unlock()
|
||||
if rerr != nil {
|
||||
klog.Errorf("virtualMachineScaleSetsClient.DeleteInstancesAsync for instances %v failed: %v", requiredIds.InstanceIds, rerr)
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ func TestDeleteNodes(t *testing.T) {
|
|||
|
||||
mockVMSSClient := mockvmssclient.NewMockInterface(ctrl)
|
||||
mockVMSSClient.EXPECT().List(gomock.Any(), manager.config.ResourceGroup).Return(expectedScaleSets, nil).Times(2)
|
||||
mockVMSSClient.EXPECT().DeleteInstancesAsync(gomock.Any(), manager.config.ResourceGroup, gomock.Any(), gomock.Any()).Return(nil, nil)
|
||||
mockVMSSClient.EXPECT().DeleteInstancesAsync(gomock.Any(), manager.config.ResourceGroup, gomock.Any(), gomock.Any(), false).Return(nil, nil)
|
||||
mockVMSSClient.EXPECT().WaitForDeleteInstancesResult(gomock.Any(), gomock.Any(), manager.config.ResourceGroup).Return(&http.Response{StatusCode: http.StatusOK}, nil).AnyTimes()
|
||||
manager.azClient.virtualMachineScaleSetsClient = mockVMSSClient
|
||||
mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl)
|
||||
|
|
@ -362,7 +362,7 @@ func TestDeleteNodeUnregistered(t *testing.T) {
|
|||
|
||||
mockVMSSClient := mockvmssclient.NewMockInterface(ctrl)
|
||||
mockVMSSClient.EXPECT().List(gomock.Any(), manager.config.ResourceGroup).Return(expectedScaleSets, nil).Times(2)
|
||||
mockVMSSClient.EXPECT().DeleteInstancesAsync(gomock.Any(), manager.config.ResourceGroup, gomock.Any(), gomock.Any()).Return(nil, nil)
|
||||
mockVMSSClient.EXPECT().DeleteInstancesAsync(gomock.Any(), manager.config.ResourceGroup, gomock.Any(), gomock.Any(), false).Return(nil, nil)
|
||||
mockVMSSClient.EXPECT().WaitForDeleteInstancesResult(gomock.Any(), gomock.Any(), manager.config.ResourceGroup).Return(&http.Response{StatusCode: http.StatusOK}, nil).AnyTimes()
|
||||
manager.azClient.virtualMachineScaleSetsClient = mockVMSSClient
|
||||
mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
//go:build !gce && !aws && !azure && !kubemark && !alicloud && !magnum && !digitalocean && !clusterapi && !huaweicloud && !ionoscloud && !linode && !hetzner && !bizflycloud && !brightbox && !packet && !vultr
|
||||
// +build !gce,!aws,!azure,!kubemark,!alicloud,!magnum,!digitalocean,!clusterapi,!huaweicloud,!ionoscloud,!linode,!hetzner,!bizflycloud,!brightbox,!packet,!vultr
|
||||
//go:build !gce && !aws && !azure && !kubemark && !alicloud && !magnum && !digitalocean && !clusterapi && !huaweicloud && !ionoscloud && !linode && !hetzner && !bizflycloud && !brightbox && !packet && !oci && !vultr
|
||||
// +build !gce,!aws,!azure,!kubemark,!alicloud,!magnum,!digitalocean,!clusterapi,!huaweicloud,!ionoscloud,!linode,!hetzner,!bizflycloud,!brightbox,!packet,!oci,!vultr
|
||||
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
|
|
@ -37,6 +37,7 @@ import (
|
|||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/ionoscloud"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/linode"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/magnum"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/ovhcloud"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/packet"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/vultr"
|
||||
|
|
@ -56,6 +57,7 @@ var AvailableCloudProviders = []string{
|
|||
cloudprovider.ExoscaleProviderName,
|
||||
cloudprovider.HuaweicloudProviderName,
|
||||
cloudprovider.HetznerProviderName,
|
||||
cloudprovider.OracleCloudProviderName,
|
||||
cloudprovider.OVHcloudProviderName,
|
||||
cloudprovider.ClusterAPIProviderName,
|
||||
cloudprovider.IonoscloudProviderName,
|
||||
|
|
@ -107,6 +109,8 @@ func buildCloudProvider(opts config.AutoscalingOptions, do cloudprovider.NodeGro
|
|||
return ionoscloud.BuildIonosCloud(opts, do, rl)
|
||||
case cloudprovider.LinodeProviderName:
|
||||
return linode.BuildLinode(opts, do, rl)
|
||||
case cloudprovider.OracleCloudProviderName:
|
||||
return oci.BuildOCI(opts, do, rl)
|
||||
case cloudprovider.VultrProviderName:
|
||||
return vultr.BuildVultr(opts, do, rl)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
//go:build oci
|
||||
// +build oci
|
||||
|
||||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package builder
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/config"
|
||||
)
|
||||
|
||||
// AvailableCloudProviders supported by the cloud provider builder.
|
||||
var AvailableCloudProviders = []string{
|
||||
cloudprovider.OracleCloudProviderName,
|
||||
}
|
||||
|
||||
// DefaultCloudProvider for oci-only build is oci.
|
||||
const DefaultCloudProvider = cloudprovider.OracleCloudProviderName
|
||||
|
||||
func buildCloudProvider(opts config.AutoscalingOptions, do cloudprovider.NodeGroupDiscoveryOptions, rl *cloudprovider.ResourceLimiter) cloudprovider.CloudProvider {
|
||||
switch opts.CloudProviderName {
|
||||
case cloudprovider.OracleCloudProviderName:
|
||||
return oci.BuildOCI(opts, do, rl)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -60,6 +60,8 @@ const (
|
|||
HuaweicloudProviderName = "huaweicloud"
|
||||
// IonoscloudProviderName gets the provider name of ionoscloud
|
||||
IonoscloudProviderName = "ionoscloud"
|
||||
// OracleCloudProviderName gets the provider name of oci
|
||||
OracleCloudProviderName = "oci"
|
||||
// OVHcloudProviderName gets the provider name of ovhcloud
|
||||
OVHcloudProviderName = "ovhcloud"
|
||||
// LinodeProviderName gets the provider name of linode
|
||||
|
|
|
|||
|
|
@ -49,12 +49,13 @@ type MigInfoProvider interface {
|
|||
}
|
||||
|
||||
type cachingMigInfoProvider struct {
|
||||
mutex sync.Mutex
|
||||
migInfoMutex sync.Mutex
|
||||
cache *GceCache
|
||||
migLister MigLister
|
||||
gceClient AutoscalingGceClient
|
||||
projectId string
|
||||
concurrentGceRefreshes int
|
||||
migInstanceMutex sync.Mutex
|
||||
}
|
||||
|
||||
// NewCachingMigInfoProvider creates an instance of caching MigInfoProvider
|
||||
|
|
@ -85,6 +86,9 @@ func (c *cachingMigInfoProvider) GetMigInstances(migRef GceRef) ([]cloudprovider
|
|||
|
||||
// GetMigForInstance returns MIG ref for a given instance
|
||||
func (c *cachingMigInfoProvider) GetMigForInstance(instanceRef GceRef) (Mig, error) {
|
||||
c.migInstanceMutex.Lock()
|
||||
defer c.migInstanceMutex.Unlock()
|
||||
|
||||
mig, found, err := c.getCachedMigForInstance(instanceRef)
|
||||
if found {
|
||||
return mig, err
|
||||
|
|
@ -160,8 +164,8 @@ func (c *cachingMigInfoProvider) fillMigInstances(migRef GceRef) error {
|
|||
}
|
||||
|
||||
func (c *cachingMigInfoProvider) GetMigTargetSize(migRef GceRef) (int64, error) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
c.migInfoMutex.Lock()
|
||||
defer c.migInfoMutex.Unlock()
|
||||
|
||||
targetSize, found := c.cache.GetMigTargetSize(migRef)
|
||||
if found {
|
||||
|
|
@ -185,8 +189,8 @@ func (c *cachingMigInfoProvider) GetMigTargetSize(migRef GceRef) (int64, error)
|
|||
}
|
||||
|
||||
func (c *cachingMigInfoProvider) GetMigBasename(migRef GceRef) (string, error) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
c.migInfoMutex.Lock()
|
||||
defer c.migInfoMutex.Unlock()
|
||||
|
||||
basename, found := c.cache.GetMigBasename(migRef)
|
||||
if found {
|
||||
|
|
@ -210,8 +214,8 @@ func (c *cachingMigInfoProvider) GetMigBasename(migRef GceRef) (string, error) {
|
|||
}
|
||||
|
||||
func (c *cachingMigInfoProvider) GetMigInstanceTemplateName(migRef GceRef) (string, error) {
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
c.migInfoMutex.Lock()
|
||||
defer c.migInfoMutex.Unlock()
|
||||
|
||||
templateName, found := c.cache.GetMigInstanceTemplateName(migRef)
|
||||
if found {
|
||||
|
|
@ -240,8 +244,8 @@ func (c *cachingMigInfoProvider) GetMigInstanceTemplate(migRef GceRef) (*gce.Ins
|
|||
return nil, err
|
||||
}
|
||||
|
||||
c.mutex.Lock()
|
||||
defer c.mutex.Unlock()
|
||||
c.migInfoMutex.Lock()
|
||||
defer c.migInfoMutex.Unlock()
|
||||
|
||||
template, found := c.cache.GetMigInstanceTemplate(migRef)
|
||||
if found && template.Name == templateName {
|
||||
|
|
@ -257,7 +261,7 @@ func (c *cachingMigInfoProvider) GetMigInstanceTemplate(migRef GceRef) (*gce.Ins
|
|||
return template, nil
|
||||
}
|
||||
|
||||
// filMigInfoCache needs to be called with mutex locked
|
||||
// filMigInfoCache needs to be called with migInfoMutex locked
|
||||
func (c *cachingMigInfoProvider) fillMigInfoCache() error {
|
||||
var zones []string
|
||||
for zone := range c.listAllZonesWithMigs() {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
approvers:
|
||||
#- jlamillan
|
||||
reviewers:
|
||||
#- jlamillan
|
||||
#- ericrrath
|
||||
|
|
@ -0,0 +1,220 @@
|
|||
# Cluster Autoscaler for Oracle Cloud Infrastructure (OCI)
|
||||
|
||||
On OCI, the cluster-autoscaler utilizes [Instance Pools](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/creatinginstancepool.htm)
|
||||
combined with [Instance Configurations](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/creatinginstanceconfig.htm) to
|
||||
automatically resize a cluster's nodes based on application workload demands by:
|
||||
|
||||
- adding nodes to static instance-pool(s) when a pod cannot be scheduled in the cluster because of insufficient resource constraints.
|
||||
- removing nodes from an instance-pool(s) when the nodes have been underutilized for an extended time, and when pods can be placed on other existing nodes.
|
||||
|
||||
The cluster-autoscaler works on a per-instance pool basis. You configure the cluster-autoscaler to tell it which instance pools to target
|
||||
for expansion and contraction, the minimum and maximum sizes for each pool, and how you want the autoscaling to take place.
|
||||
Instance pools not referenced in the configuration file are not managed by the cluster-autoscaler.
|
||||
|
||||
## Create Required OCI Resources
|
||||
|
||||
### IAM Policy (if using Instance Principals)
|
||||
|
||||
We recommend setting up and configuring the cluster-autoscaler to use
|
||||
[Instance Principals](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm)
|
||||
to authenticate to the OCI APIs.
|
||||
|
||||
The following policy provides the minimum privileges necessary for Cluster Autoscaler to run:
|
||||
|
||||
1: Create a compartment-level dynamic group containing the nodes (compute instances) in the cluster:
|
||||
|
||||
```
|
||||
All {instance.compartment.id = 'ocid1.compartment.oc1..aaaaaaaa7ey4sg3a6b5wnv5hlkjlkjadslkfjalskfjalsadfadsf'}
|
||||
```
|
||||
|
||||
2: Create a *tenancy-level* policy to allow nodes to manage instance-pools:
|
||||
|
||||
```
|
||||
Allow dynamic-group acme-oci-cluster-autoscaler-dyn-grp to manage instance-pools in compartment <compartment-name>
|
||||
Allow dynamic-group acme-oci-cluster-autoscaler-dyn-grp to manage instance-configurations in compartment <compartment-name>
|
||||
Allow dynamic-group acme-oci-cluster-autoscaler-dyn-grp to manage instance-family in compartment <compartment-name>
|
||||
Allow dynamic-group acme-oci-cluster-autoscaler-dyn-grp to use subnets in compartment <compartment-name>
|
||||
Allow dynamic-group acme-oci-cluster-autoscaler-dyn-grp to read virtual-network-family in compartment <compartment-name>
|
||||
Allow dynamic-group acme-oci-cluster-autoscaler-dyn-grp to use vnics in compartment <compartment-name>
|
||||
Allow dynamic-group acme-oci-cluster-autoscaler-dyn-grp to inspect compartments in compartment <compartment-name>
|
||||
```
|
||||
|
||||
### Instance Pool and Instance Configurations
|
||||
|
||||
Before you deploy the cluster auto-scaler on OCI, your need to create one or more static Instance Pools and Instance
|
||||
Configuration with `cloud-init` specified in the launch details so new nodes automatically joins the existing cluster on
|
||||
start up.
|
||||
|
||||
Advanced Instance Pool and Instance Configuration configuration is out of scope for this document. However, a
|
||||
working [instance-details.json](./examples/instance-details.json) and [placement-config.json](./examples/placement-config.json)
|
||||
([example](./examples/instance-details.json) based on Rancher [RKE](https://rancher.com/products/rke/)) using [cloud-init](https://cloudinit.readthedocs.io/en/latest/) are
|
||||
included in the examples, which can be applied using the [OCI CLI](https://docs.oracle.com/en-us/iaas/Content/API/SDKDocs/cliinstall.htm).
|
||||
|
||||
Modify the `user_data` in the example [instance-details.json](./examples/instance-details.json) to suit your needs, re-base64 encode, apply:
|
||||
|
||||
```bash
|
||||
# e.g. cloud-init. Modify, re-encode, and update user_data in instance-details.json to suit your needs:
|
||||
|
||||
$ echo IyEvYmluL2Jhc2gKdG91hci9saWIvYXB0L....1yZXRyeSAzIGhG91Y2ggL3RtcC9jbG91ZC1pbml0LWZpbmlzaGVkCg== | base64 -D
|
||||
|
||||
#!/bin/bash
|
||||
groupadd docker
|
||||
usermod -aG docker ubuntu
|
||||
curl --retry 3 https://releases.rancher.com/install-docker/20.10.sh | sh
|
||||
docker run -d --privileged --restart=unless-stopped --net=host -v /etc/kubernetes:/etc/kubernetes -v /var/run:/var/run rancher/rancher-agent:v2.5.5 --server https://my-rancher.com --token xxxxxx --worker
|
||||
```
|
||||
|
||||
```bash
|
||||
$ oci compute-management instance-configuration create --instance-details file://./cluster-autoscaler/cloudprovider/oci/examples/instance-details.json --compartment-id ocid1.compartment.oc1..aaaaaaaa7ey4sg3a6b5wnv5hlkjlkjadslkfjalskfjalsadfadsf --query 'data.id' --raw-output
|
||||
|
||||
ocid1.instanceconfiguration.oc1.phx.aaaaaaaa3neul67zb3goz43lybosc2o3fv67gj3zazexbb3vfcbypmpznhtq
|
||||
|
||||
$ oci compute-management instance-pool create --compartment-id ocid1.compartment.oc1..aaaaaaaa7ey4sg3a6b5wnv5hlkjlkjadslkfjalskfjalsadfadsf --instance-configuration-id ocid1.instanceconfiguration.oc1.phx.aaaaaaaa3neul67zb3goz43lybosc2o3fv67gj3zazexbb3vfcbypmpznhtq --placement-configurations file://./cluster-autoscaler/cloudprovider/oci/examples/placement-config.json --size 0 --wait-for-state RUNNING --query 'data.id' --raw-output
|
||||
|
||||
Action completed. Waiting until the resource has entered state: ('RUNNING',)
|
||||
ocid1.instancepool.oc1.phx.aaaaaaaayd5bxwrzomzr2b2enchm4mof7uhw7do5hc2afkhks576syikk2ca
|
||||
```
|
||||
|
||||
## Configure Autoscaler
|
||||
|
||||
Use the `--nodes=<min-nodes>:<max-nodes>:<instancepool-ocid>` parameter to specify which pre-existing instance
|
||||
pools to target for automatic expansion and contraction, the minimum and maximum sizes for each node pool, and how you
|
||||
want the autoscaling to take place. Instance pools not referenced in the configuration file are not managed by the
|
||||
autoscaler where:
|
||||
|
||||
- `<min-nodes>` is the minimum number of nodes allowed in the instance-pool.
|
||||
- `<max-nodes>` is the maximum number of nodes allowed in the instance-pool. Make sure the maximum number of nodes you specify does not exceed the tenancy limits for the node shape defined for the node pool.
|
||||
- `<instancepool-ocid>` is the OCIDs of a pre-existing instance-pool.
|
||||
|
||||
If you are authenticating via instance principals, be sure the `OCI_REGION` environment variable is set to the correct
|
||||
value in the deployment e.g.:
|
||||
|
||||
```yaml
|
||||
env:
|
||||
- name: OCI_REGION
|
||||
value: "us-phoenix-1"
|
||||
```
|
||||
|
||||
### Optional cloud-config file
|
||||
|
||||
_Optional_ cloud-config file mounted in the path specified by `--cloud-config`.
|
||||
|
||||
An example, of passing optional configuration via `cloud-config` file that uses configures the cluster-autoscaler to use
|
||||
instance-principals authenticating via instance principalsand only see configured instance-pools in a single compartment:
|
||||
|
||||
```ini
|
||||
[Global]
|
||||
compartment-id = ocid1.compartment.oc1..aaaaaaaa7ey4sg3a6b5wnv5hlkjlkjadslkfjalskfjalsadfadsf
|
||||
region = uk-london-1
|
||||
use-instance-principals = true
|
||||
```
|
||||
|
||||
### Environment variables
|
||||
|
||||
Configuration via environment-variables:
|
||||
|
||||
- `OCI_USE_INSTANCE_PRINCIPAL` - Whether to use Instance Principals for authentication rather than expecting an OCI config file to be mounted in the container. Defaults to false.
|
||||
- `OCI_REGION` - **Required** when using Instance Principals. e.g. `OCI_REGION=us-phoenix-1`. See [region list](https://docs.oracle.com/en-us/iaas/Content/General/Concepts/regions.htm) for identifiers.
|
||||
- `OCI_COMPARTMENT_ID` - Restrict the cluster-autoscaler to instance-pools in a single compartment. When unset, the cluster-autoscaler will manage each specified instance-pool no matter which compartment they are in.
|
||||
- `OCI_REFRESH_INTERVAL` - Optional refresh interval to sync internal cache with OCI API defaults to `2m`.
|
||||
|
||||
## Deployment
|
||||
|
||||
### Create OCI config secret (only if _not_ using Instance Principals)
|
||||
|
||||
If you are opting for a file based OCI configuration (as opposed to instance principals), the OCI config file and private key need to be mounted into the container filesystem using a secret volume.
|
||||
|
||||
The following policy is required when the specified is not an administrator to run the cluster-autoscaler:
|
||||
|
||||
```
|
||||
Allow group acme-oci-cluster-autoscaler-user-grp to manage instance-pools in compartment <compartment-name>
|
||||
Allow group acme-oci-cluster-autoscaler-user-grp to manage instance-configurations in compartment <compartment-name>
|
||||
Allow group acme-oci-cluster-autoscaler-user-grp to manage instance-family in compartment <compartment-name>
|
||||
Allow group acme-oci-cluster-autoscaler-user-grp to use subnets in compartment <compartment-name>
|
||||
Allow group acme-oci-cluster-autoscaler-user-grp to read virtual-network-family in compartment <compartment-name>
|
||||
Allow group acme-oci-cluster-autoscaler-user-grp to use vnics in compartment <compartment-name>
|
||||
Allow group acme-oci-cluster-autoscaler-user-grp to inspect compartments in compartment <compartment-name>
|
||||
```
|
||||
|
||||
Example OCI config file (note `key_file` is the expected path and filename of the OCI API private-key from the perspective of the container):
|
||||
|
||||
```bash
|
||||
$ cat ~/.oci/config
|
||||
|
||||
[DEFAULT]
|
||||
user=ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
fingerprint=xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx
|
||||
key_file=/root/.oci/api_key.pem
|
||||
tenancy=ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
pass_phrase=
|
||||
region=us-phoenix-1
|
||||
```
|
||||
|
||||
Create the secret (`api_key.pem` key name is required):
|
||||
|
||||
```bash
|
||||
kubectl create secret generic oci-config -n kube-system --from-file=/Users/me/.oci/config --from-file=api_key.pem=/Users/me/.oci/my_api_key.pem
|
||||
```
|
||||
|
||||
### Example Deployment
|
||||
|
||||
Two example deployments of the cluster-autoscaler that manage instancepools are located in the [examples](./examples/) directory.
|
||||
[oci-ip-cluster-autoscaler-w-principals.yaml](./examples/oci-ip-cluster-autoscaler-w-principals.yaml) uses
|
||||
instance principals, and [oci-ip-cluster-autoscaler-w-config.yaml](./examples/oci-ip-cluster-autoscaler-w-config.yaml) uses file
|
||||
based authentication.
|
||||
|
||||
Note the 3 specified instance-pools are intended to correspond to different availability domains in the Phoenix, AZ region:
|
||||
|
||||
```yaml
|
||||
...
|
||||
containers:
|
||||
- image: docker.io/jlamillan/autoscaler:oci-pr-rc6
|
||||
name: cluster-autoscaler
|
||||
command:
|
||||
- ./cluster-autoscaler
|
||||
- --cloud-provider=oci
|
||||
- --nodes=1:10:ocid1.instancepool.oc1.phx.aaaaaaaaqdxy35acq32zjfvkybjmvlbdgj6q3m55qkwwctxhsprmz633k62q
|
||||
- --nodes=0:10:ocid1.instancepool.oc1.phx.aaaaaaaazldzcu4mi5spz56upbtwnsynz2nk6jvmx7zi4hsta4uggxbulbua
|
||||
- --nodes=0:20:ocid1.instancepool.oc1.phx.aaaaaaaal3jhoc32ljsfaeif4x2ssfa2a63oehjgqryiueivieee6yaqbkia
|
||||
```
|
||||
|
||||
Instance principal based authentication deployment:
|
||||
|
||||
Substitute the OCIDs of _your_ instance pool(s) and set the `OCI_REGION` environment variable to the region where your
|
||||
instance pool(s) reside before applying the deployment:
|
||||
|
||||
```
|
||||
kubectl apply -f ./cloudprovider/oci/examples/oci-ip-cluster-autoscaler-w-principals.yaml
|
||||
```
|
||||
|
||||
OCI config file based authentication deployment:
|
||||
|
||||
```
|
||||
kubectl apply -f ./cloudprovider/oci/examples/oci-ip-cluster-autoscaler-w-config.yaml
|
||||
```
|
||||
|
||||
## Common Notes and Gotchas:
|
||||
- You must configure the instance configuration of new compute instances to join the existing cluster when they start. This can
|
||||
be accomplished with `cloud-init` / `user-data` in the instance launch configuration [example](./examples/instance-details.json).
|
||||
- If opting for a file based OCI configuration (as opposed to instance principals), ensure the OCI config and private-key
|
||||
PEM files are mounted into the container filesystem at the [expected path](https://docs.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm). Note the `key_file` option in the example `~/.oci/config` above references a private-key file mounted into container by the example [volumeMount](./examples/oci-ip-cluster-autoscaler-w-config.yaml#L165)
|
||||
- Make sure the maximum number of nodes you specify does not exceed the limit for the instance-pool or the tenancy.
|
||||
- We recommend creating multiple instance-pools with one availability domain specified so new nodes can be created to meet
|
||||
affinity requirements across availability domains.
|
||||
- If you are authenticating via instance principals, be sure the `OCI_REGION` environment variable is set to the correct
|
||||
value in the deployment.
|
||||
- The cluster-autoscaler will not automatically remove scaled down (terminated) `Node` objects from the Kubernetes API
|
||||
without assistance from the [OCI Cloud Controller Manager](https://github.com/oracle/oci-cloud-controller-manager) (CCM).
|
||||
If scaled down nodes are lingering in your cluster in the `NotReady` status, ensure the OCI CCM is installed and running
|
||||
correctly (`oci-cloud-controller-manager`).
|
||||
- Avoid manually changing node pools that are managed by the cluster-autoscaler. For example, do not add or remove nodes
|
||||
using kubectl, or using the Console (or the Oracle Cloud Infrastructure CLI or API).
|
||||
- `--node-group-auto-discovery` and `--node-autoprovisioning-enabled=true` are not supported.
|
||||
- We set a `nvidia.com/gpu:NoSchedule` taint on nodes in a GPU enabled instance-pool.
|
||||
|
||||
## Helpful links
|
||||
- [Oracle Cloud Infrastructure home](https://cloud.oracle.com)
|
||||
- [OCI instance configuration documentation](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/creatinginstanceconfig.htm)
|
||||
- [instance principals](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm)
|
||||
- [OCI Cloud Controller Manager](https://github.com/oracle/oci-cloud-controller-manager)
|
||||
- [OCI Container Storage Interface driver](https://github.com/oracle/oci-cloud-controller-manager/blob/master/container-storage-interface.md)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"instanceType": "compute",
|
||||
"launchDetails": {
|
||||
"compartmentId": "ocid1.compartment.oc1..aaaaaaaa7ey4sg3a6b5wnv5hlkjlkjadslkfjalskfjalsadfadsf",
|
||||
"shape": "VM.Standard2.8",
|
||||
"sourceDetails":
|
||||
{
|
||||
"imageId": "ocid1.image.oc1.phx.aaaaaaaa55tzajot4gbiw2p7gquwjnvfzrasosbrq4h6wywkff4zjosp2fia",
|
||||
"sourceType": "image",
|
||||
"bootVolumeSizeInGBs": 100
|
||||
},
|
||||
"metadata": {
|
||||
"user_data": "IyEvYmluL2Jhc2gKdG91Y2ggL3RtcC9jbG91ZC1pbml0LXN0YXJ0ZWQKaXB0YWJsZXMgLUYKZ3JvdXBhZGQgZG9ja2VyCnVzZXJtb2QgLWFHIGRvY2tlciB1YnVudHUKcm0gL3Zhci9saWIvYXB0L2xpc3RzL2xvY2sKcGtpbGwgLTkgLWYgYXB0CmN1cmwgLS1yZXRyeSAzIGh0dHBzOi8vcmVsZWFzZXMucmFuY2hlci5jb20vaW5zdGFsbC1kb2NrZXIvMjAuMTAuc2ggfCBzaApkb2NrZXIgcnVuIC1kIC0tcHJpdmlsZWdlZCAtLXJlc3RhcnQ9dW5sZXNzLXN0b3BwZWQgLS1uZXQ9aG9zdCAtdiAvZXRjL2t1YmVybmV0ZXM6L2V0Yy9rdWJlcm5ldGVzIC12IC92YXIvcnVuOi92YXIvcnVuIHJhbmNoZXIvcmFuY2hlci1hZ2VudDp2Mi41LjUgLS1zZXJ2ZXIgaHR0cHM6Ly9teS1yYW5jaGVyLmNvbSAtLXRva2VuIHh4eHh4eCAgLS13b3JrZXIKdG91Y2ggL3RtcC9jbG91ZC1pbml0LWZpbmlzaGVkCg=="
|
||||
},
|
||||
"createVnicDetails": {
|
||||
"assignPublicIp": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,174 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["events", "endpoints"]
|
||||
verbs: ["create", "patch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/eviction"]
|
||||
verbs: ["create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/status"]
|
||||
verbs: ["update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["endpoints"]
|
||||
resourceNames: ["cluster-autoscaler"]
|
||||
verbs: ["get", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["watch", "list", "get", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namepaces"]
|
||||
verbs: ["list"]
|
||||
- apiGroups: [""]
|
||||
resources:
|
||||
- "pods"
|
||||
- "services"
|
||||
- "replicationcontrollers"
|
||||
- "persistentvolumeclaims"
|
||||
- "persistentvolumes"
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["extensions"]
|
||||
resources: ["replicasets", "daemonsets"]
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["policy"]
|
||||
resources: ["poddisruptionbudgets"]
|
||||
verbs: ["watch", "list"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["statefulsets", "replicasets", "daemonsets"]
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["storageclasses", "csinodes"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["batch"]
|
||||
resources: ["jobs", "cronjobs"]
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resources: ["leases"]
|
||||
verbs: ["create"]
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resourceNames: ["cluster-autoscaler"]
|
||||
resources: ["leases"]
|
||||
verbs: ["get", "update"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["csidrivers", "csistoragecapacities"]
|
||||
verbs: ["get", "list"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["create","list","watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
resourceNames:
|
||||
- "cluster-autoscaler-status"
|
||||
- "cluster-autoscaler-priority-expander"
|
||||
verbs: ["delete", "get", "update", "watch"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-autoscaler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: cluster-autoscaler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
labels:
|
||||
app: cluster-autoscaler
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cluster-autoscaler
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cluster-autoscaler
|
||||
spec:
|
||||
serviceAccountName: cluster-autoscaler
|
||||
containers:
|
||||
- image: docker.io/jlamillan/autoscaler:oci-pr-rc6
|
||||
name: cluster-autoscaler
|
||||
command:
|
||||
- ./cluster-autoscaler
|
||||
- --v=5
|
||||
- --logtostderr=true
|
||||
- --cloud-provider=oci
|
||||
- --nodes=0:10:ocid1.instancepool.oc1.phx.aaaaaaaaqdxy35acq32zjfvkybjmvlbdgj6q3m55qkwwctxhsprmz633k62q
|
||||
- --nodes=0:10:ocid1.instancepool.oc1.phx.aaaaaaaazldzcu4mi5spz56upbtwnsynz2nk6jvmx7zi4hsta4uggxbulbua
|
||||
- --nodes=0:10:ocid1.instancepool.oc1.phx.aaaaaaaal3jhoc32ljsfaeif4x2ssfa2a63oehjgqryiueivieee6yaqbkia
|
||||
- --scale-down-delay-after-add=1m
|
||||
- --scale-down-unneeded-time=1m
|
||||
- --namespace=kube-system
|
||||
imagePullPolicy: "Always"
|
||||
env:
|
||||
- name: OCI_USE_INSTANCE_PRINCIPAL
|
||||
value: "false"
|
||||
volumeMounts:
|
||||
- name: oci-config-vol
|
||||
mountPath: "/root/.oci"
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: oci-config-vol
|
||||
secret:
|
||||
secretName: oci-config
|
||||
items:
|
||||
- key: config
|
||||
path: config
|
||||
- key: api_key.pem
|
||||
path: api_key.pem
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["events", "endpoints"]
|
||||
verbs: ["create", "patch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/eviction"]
|
||||
verbs: ["create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/status"]
|
||||
verbs: ["update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["endpoints"]
|
||||
resourceNames: ["cluster-autoscaler"]
|
||||
verbs: ["get", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["watch", "list", "get", "update"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["list"]
|
||||
- apiGroups: [""]
|
||||
resources:
|
||||
- "pods"
|
||||
- "services"
|
||||
- "replicationcontrollers"
|
||||
- "persistentvolumeclaims"
|
||||
- "persistentvolumes"
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["extensions"]
|
||||
resources: ["replicasets", "daemonsets"]
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["policy"]
|
||||
resources: ["poddisruptionbudgets"]
|
||||
verbs: ["watch", "list"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["statefulsets", "replicasets", "daemonsets"]
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["storageclasses", "csinodes"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: ["batch"]
|
||||
resources: ["jobs", "cronjobs"]
|
||||
verbs: ["watch", "list", "get"]
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resources: ["leases"]
|
||||
verbs: ["create"]
|
||||
- apiGroups: ["coordination.k8s.io"]
|
||||
resourceNames: ["cluster-autoscaler"]
|
||||
resources: ["leases"]
|
||||
verbs: ["get", "update"]
|
||||
- apiGroups: ["storage.k8s.io"]
|
||||
resources: ["csidrivers", "csistoragecapacities"]
|
||||
verbs: ["get", "list"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
verbs: ["create","list","watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["configmaps"]
|
||||
resourceNames:
|
||||
- "cluster-autoscaler-status"
|
||||
- "cluster-autoscaler-priority-expander"
|
||||
verbs: ["delete", "get", "update", "watch"]
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-autoscaler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
labels:
|
||||
k8s-addon: cluster-autoscaler.addons.k8s.io
|
||||
k8s-app: cluster-autoscaler
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: cluster-autoscaler
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: cluster-autoscaler
|
||||
namespace: kube-system
|
||||
labels:
|
||||
app: cluster-autoscaler
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: cluster-autoscaler
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: cluster-autoscaler
|
||||
spec:
|
||||
serviceAccountName: cluster-autoscaler
|
||||
containers:
|
||||
- image: docker.io/jlamillan/autoscaler:oci-pr-rc6
|
||||
name: cluster-autoscaler
|
||||
command:
|
||||
- ./cluster-autoscaler
|
||||
- --v=5
|
||||
- --logtostderr=true
|
||||
- --cloud-provider=oci
|
||||
- --nodes=0:10:ocid1.instancepool.oc1.phx.aaaaaaaaqdxy35acq32zjfvkybjmvlbdgj6q3m55qkwwctxhsprmz633k62q
|
||||
- --nodes=0:10:ocid1.instancepool.oc1.phx.aaaaaaaazldzcu4mi5spz56upbtwnsynz2nk6jvmx7zi4hsta4uggxbulbua
|
||||
- --nodes=1:10:ocid1.instancepool.oc1.phx.aaaaaaaal3jhoc32ljsfaeif4x2ssfa2a63oehjgqryiueivieee6yaqbkia
|
||||
- --scale-down-delay-after-add=10m
|
||||
- --scale-down-unneeded-time=10m
|
||||
- --namespace=kube-system
|
||||
imagePullPolicy: "Always"
|
||||
env:
|
||||
- name: OCI_USE_INSTANCE_PRINCIPAL
|
||||
value: "true"
|
||||
- name: OCI_REGION
|
||||
value: "us-phoenix-1"
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
[
|
||||
{
|
||||
"availabilityDomain": "hXgQ:PHX-AD-2",
|
||||
"primarySubnetId": "ocid1.subnet.oc1.phx.aaaaaaaaouihv645dp2xaee6w4uvx6emjwuscsrxcn3miwa6vmijtpdnqdeq"
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
Copyright (c) 2016, 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl
|
||||
or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
____________________________
|
||||
The Universal Permissive License (UPL), Version 1.0
|
||||
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Subject to the condition set forth below, permission is hereby granted to any person obtaining a copy of this software, associated documentation and/or data (collectively the "Software"), free of charge and under any and all copyright rights in the Software, and any and all patent rights owned or freely licensable by each licensor hereunder covering either (i) the unmodified Software as contributed to or provided by such licensor, or (ii) the Larger Works (as defined below), to deal in both
|
||||
|
||||
(a) the Software, and
|
||||
(b) any piece of software and/or hardware listed in the lrgrwrks.txt file if one is included with the Software (each a "Larger Work" to which the Software is contributed by such licensors),
|
||||
|
||||
without restriction, including without limitation the rights to copy, create derivative works of, display, perform, and distribute the Software and make, use, sell, offer for sale, import, export, have made, and have sold the Software and the Larger Work(s), and to sublicense the foregoing rights on either these or other terms.
|
||||
|
||||
This license is subject to the following condition:
|
||||
|
||||
The above copyright notice and either this complete permission notice or at a minimum a reference to the UPL must be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
The Apache Software License, Version 2.0
|
||||
Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License"); You may not use this product except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. A copy of the license is also reproduced below. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
Apache License
|
||||
|
||||
Version 2.0, January 2004
|
||||
|
||||
http://www.apache.org/licenses/
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
1. Definitions.
|
||||
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
||||
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
||||
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
||||
3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
||||
4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
||||
You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
||||
6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
||||
8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
||||
9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
@ -0,0 +1 @@
|
|||
Copyright (c) 2016, 2018, 2020, Oracle and/or its affiliates.
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// x509CertificateRetriever provides an X509 certificate with the RSA private key
|
||||
type x509CertificateRetriever interface {
|
||||
Refresh() error
|
||||
CertificatePemRaw() []byte
|
||||
Certificate() *x509.Certificate
|
||||
PrivateKeyPemRaw() []byte
|
||||
PrivateKey() *rsa.PrivateKey
|
||||
}
|
||||
|
||||
// urlBasedX509CertificateRetriever retrieves PEM-encoded X509 certificates from the given URLs.
|
||||
type urlBasedX509CertificateRetriever struct {
|
||||
certURL string
|
||||
privateKeyURL string
|
||||
passphrase string
|
||||
certificatePemRaw []byte
|
||||
certificate *x509.Certificate
|
||||
privateKeyPemRaw []byte
|
||||
privateKey *rsa.PrivateKey
|
||||
mux sync.Mutex
|
||||
dispatcher common.HTTPRequestDispatcher
|
||||
}
|
||||
|
||||
func newURLBasedX509CertificateRetriever(dispatcher common.HTTPRequestDispatcher, certURL, privateKeyURL, passphrase string) x509CertificateRetriever {
|
||||
return &urlBasedX509CertificateRetriever{
|
||||
certURL: certURL,
|
||||
privateKeyURL: privateKeyURL,
|
||||
passphrase: passphrase,
|
||||
mux: sync.Mutex{},
|
||||
dispatcher: dispatcher,
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh() is failure atomic, i.e., CertificatePemRaw(), Certificate(), PrivateKeyPemRaw(), and PrivateKey() would
|
||||
// return their previous values if Refresh() fails.
|
||||
func (r *urlBasedX509CertificateRetriever) Refresh() error {
|
||||
common.Debugln("Refreshing certificate")
|
||||
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
var err error
|
||||
|
||||
var certificatePemRaw []byte
|
||||
var certificate *x509.Certificate
|
||||
if certificatePemRaw, certificate, err = r.renewCertificate(r.certURL); err != nil {
|
||||
return fmt.Errorf("failed to renew certificate: %s", err.Error())
|
||||
}
|
||||
|
||||
var privateKeyPemRaw []byte
|
||||
var privateKey *rsa.PrivateKey
|
||||
if r.privateKeyURL != "" {
|
||||
if privateKeyPemRaw, privateKey, err = r.renewPrivateKey(r.privateKeyURL, r.passphrase); err != nil {
|
||||
return fmt.Errorf("failed to renew private key: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
r.certificatePemRaw = certificatePemRaw
|
||||
r.certificate = certificate
|
||||
r.privateKeyPemRaw = privateKeyPemRaw
|
||||
r.privateKey = privateKey
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *urlBasedX509CertificateRetriever) renewCertificate(url string) (certificatePemRaw []byte, certificate *x509.Certificate, err error) {
|
||||
var body bytes.Buffer
|
||||
if body, _, err = httpGet(r.dispatcher, url); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to get certificate from %s: %s", url, err.Error())
|
||||
}
|
||||
|
||||
certificatePemRaw = body.Bytes()
|
||||
var block *pem.Block
|
||||
block, _ = pem.Decode(certificatePemRaw)
|
||||
if block == nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse the new certificate, not valid pem data")
|
||||
}
|
||||
|
||||
if certificate, err = x509.ParseCertificate(block.Bytes); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse the new certificate: %s", err.Error())
|
||||
}
|
||||
|
||||
return certificatePemRaw, certificate, nil
|
||||
}
|
||||
|
||||
func (r *urlBasedX509CertificateRetriever) renewPrivateKey(url, passphrase string) (privateKeyPemRaw []byte, privateKey *rsa.PrivateKey, err error) {
|
||||
var body bytes.Buffer
|
||||
if body, _, err = httpGet(r.dispatcher, url); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to get private key from %s: %s", url, err.Error())
|
||||
}
|
||||
|
||||
privateKeyPemRaw = body.Bytes()
|
||||
if privateKey, err = common.PrivateKeyFromBytes(privateKeyPemRaw, &passphrase); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse the new private key: %s", err.Error())
|
||||
}
|
||||
|
||||
return privateKeyPemRaw, privateKey, nil
|
||||
}
|
||||
|
||||
func (r *urlBasedX509CertificateRetriever) CertificatePemRaw() []byte {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if r.certificatePemRaw == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]byte, len(r.certificatePemRaw))
|
||||
copy(c, r.certificatePemRaw)
|
||||
return c
|
||||
}
|
||||
|
||||
func (r *urlBasedX509CertificateRetriever) Certificate() *x509.Certificate {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if r.certificate == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := *r.certificate
|
||||
return &c
|
||||
}
|
||||
|
||||
func (r *urlBasedX509CertificateRetriever) PrivateKeyPemRaw() []byte {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if r.privateKeyPemRaw == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]byte, len(r.privateKeyPemRaw))
|
||||
copy(c, r.privateKeyPemRaw)
|
||||
return c
|
||||
}
|
||||
|
||||
func (r *urlBasedX509CertificateRetriever) PrivateKey() *rsa.PrivateKey {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
//Nil Private keys are supported as part of a certificate
|
||||
if r.privateKey == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := *r.privateKey
|
||||
return &c
|
||||
}
|
||||
|
||||
//staticCertificateRetriever serves certificates from static data
|
||||
type staticCertificateRetriever struct {
|
||||
Passphrase []byte
|
||||
CertificatePem []byte
|
||||
PrivateKeyPem []byte
|
||||
certificate *x509.Certificate
|
||||
privateKey *rsa.PrivateKey
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
//Refresh proccess the inputs into appropiate keys and certificates
|
||||
func (r *staticCertificateRetriever) Refresh() error {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
certifcate, err := r.readCertificate()
|
||||
if err != nil {
|
||||
r.certificate = nil
|
||||
return err
|
||||
}
|
||||
r.certificate = certifcate
|
||||
|
||||
key, err := r.readPrivateKey()
|
||||
if err != nil {
|
||||
r.privateKey = nil
|
||||
return err
|
||||
}
|
||||
r.privateKey = key
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *staticCertificateRetriever) Certificate() *x509.Certificate {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
return r.certificate
|
||||
}
|
||||
|
||||
func (r *staticCertificateRetriever) PrivateKey() *rsa.PrivateKey {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
return r.privateKey
|
||||
}
|
||||
|
||||
func (r *staticCertificateRetriever) CertificatePemRaw() []byte {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if r.CertificatePem == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]byte, len(r.CertificatePem))
|
||||
copy(c, r.CertificatePem)
|
||||
return c
|
||||
}
|
||||
|
||||
func (r *staticCertificateRetriever) PrivateKeyPemRaw() []byte {
|
||||
r.mux.Lock()
|
||||
defer r.mux.Unlock()
|
||||
|
||||
if r.PrivateKeyPem == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]byte, len(r.PrivateKeyPem))
|
||||
copy(c, r.PrivateKeyPem)
|
||||
return c
|
||||
}
|
||||
|
||||
func (r *staticCertificateRetriever) readCertificate() (certificate *x509.Certificate, err error) {
|
||||
block, _ := pem.Decode(r.CertificatePem)
|
||||
if block == nil {
|
||||
return nil, fmt.Errorf("failed to parse the new certificate, not valid pem data")
|
||||
}
|
||||
|
||||
if certificate, err = x509.ParseCertificate(block.Bytes); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse the new certificate: %s", err.Error())
|
||||
}
|
||||
return certificate, nil
|
||||
}
|
||||
|
||||
func (r *staticCertificateRetriever) readPrivateKey() (*rsa.PrivateKey, error) {
|
||||
if r.PrivateKeyPem == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var pass *string
|
||||
if r.Passphrase == nil {
|
||||
pass = nil
|
||||
} else {
|
||||
ss := string(r.Passphrase)
|
||||
pass = &ss
|
||||
}
|
||||
return common.PrivateKeyFromBytes(r.PrivateKeyPem, pass)
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
type instancePrincipalConfigurationProvider struct {
|
||||
keyProvider instancePrincipalKeyProvider
|
||||
region *common.Region
|
||||
}
|
||||
|
||||
//InstancePrincipalConfigurationProvider returns a configuration for instance principals
|
||||
func InstancePrincipalConfigurationProvider() (common.ConfigurationProvider, error) {
|
||||
return newInstancePrincipalConfigurationProvider("", nil)
|
||||
}
|
||||
|
||||
//InstancePrincipalConfigurationProviderForRegion returns a configuration for instance principals with a given region
|
||||
func InstancePrincipalConfigurationProviderForRegion(region common.Region) (common.ConfigurationProvider, error) {
|
||||
return newInstancePrincipalConfigurationProvider(region, nil)
|
||||
}
|
||||
|
||||
//InstancePrincipalConfigurationProviderWithCustomClient returns a configuration for instance principals using a modifier function to modify the HTTPRequestDispatcher
|
||||
func InstancePrincipalConfigurationProviderWithCustomClient(modifier func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error)) (common.ConfigurationProvider, error) {
|
||||
return newInstancePrincipalConfigurationProvider("", modifier)
|
||||
}
|
||||
|
||||
//InstancePrincipalConfigurationForRegionWithCustomClient returns a configuration for instance principals with a given region using a modifier function to modify the HTTPRequestDispatcher
|
||||
func InstancePrincipalConfigurationForRegionWithCustomClient(region common.Region, modifier func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error)) (common.ConfigurationProvider, error) {
|
||||
return newInstancePrincipalConfigurationProvider(region, modifier)
|
||||
}
|
||||
|
||||
func newInstancePrincipalConfigurationProvider(region common.Region, modifier func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error)) (common.ConfigurationProvider, error) {
|
||||
var err error
|
||||
var keyProvider *instancePrincipalKeyProvider
|
||||
if keyProvider, err = newInstancePrincipalKeyProvider(modifier); err != nil {
|
||||
return nil, fmt.Errorf("failed to create a new key provider for instance principal: %s", err.Error())
|
||||
}
|
||||
if len(region) > 0 {
|
||||
return instancePrincipalConfigurationProvider{keyProvider: *keyProvider, region: ®ion}, nil
|
||||
}
|
||||
return instancePrincipalConfigurationProvider{keyProvider: *keyProvider, region: nil}, nil
|
||||
}
|
||||
|
||||
//InstancePrincipalConfigurationWithCerts returns a configuration for instance principals with a given region and hardcoded certificates in lieu of metadata service certs
|
||||
func InstancePrincipalConfigurationWithCerts(region common.Region, leafCertificate, leafPassphrase, leafPrivateKey []byte, intermediateCertificates [][]byte) (common.ConfigurationProvider, error) {
|
||||
leafCertificateRetriever := staticCertificateRetriever{Passphrase: leafPassphrase, CertificatePem: leafCertificate, PrivateKeyPem: leafPrivateKey}
|
||||
|
||||
//The .Refresh() call actually reads the certificates from the inputs
|
||||
err := leafCertificateRetriever.Refresh()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
certificate := leafCertificateRetriever.Certificate()
|
||||
|
||||
tenancyID := extractTenancyIDFromCertificate(certificate)
|
||||
fedClient, err := newX509FederationClientWithCerts(region, tenancyID, leafCertificate, leafPassphrase, leafPrivateKey, intermediateCertificates, *newDispatcherModifier(nil))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provider := instancePrincipalConfigurationProvider{
|
||||
keyProvider: instancePrincipalKeyProvider{
|
||||
Region: region,
|
||||
FederationClient: fedClient,
|
||||
TenancyID: tenancyID,
|
||||
},
|
||||
region: ®ion,
|
||||
}
|
||||
return provider, nil
|
||||
|
||||
}
|
||||
|
||||
func (p instancePrincipalConfigurationProvider) PrivateRSAKey() (*rsa.PrivateKey, error) {
|
||||
return p.keyProvider.PrivateRSAKey()
|
||||
}
|
||||
|
||||
func (p instancePrincipalConfigurationProvider) KeyID() (string, error) {
|
||||
return p.keyProvider.KeyID()
|
||||
}
|
||||
|
||||
func (p instancePrincipalConfigurationProvider) TenancyOCID() (string, error) {
|
||||
return p.keyProvider.TenancyOCID()
|
||||
}
|
||||
|
||||
func (p instancePrincipalConfigurationProvider) UserOCID() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p instancePrincipalConfigurationProvider) KeyFingerprint() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p instancePrincipalConfigurationProvider) Region() (string, error) {
|
||||
if p.region == nil {
|
||||
region := p.keyProvider.RegionForFederationClient()
|
||||
common.Debugf("Region in instance principal configuration provider is nil. Returning federation clients region: %s", region)
|
||||
return string(region), nil
|
||||
}
|
||||
return string(*p.region), nil
|
||||
}
|
||||
|
||||
func (p instancePrincipalConfigurationProvider) AuthType() (common.AuthConfig, error) {
|
||||
return common.AuthConfig{common.InstancePrincipal, false, nil}, fmt.Errorf("unsupported, keep the interface")
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
|
||||
//dispatcherModifier gives ability to modify a HTTPRequestDispatcher before use.
|
||||
type dispatcherModifier struct {
|
||||
modifiers []func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error)
|
||||
}
|
||||
|
||||
//newDispatcherModifier creates a new dispatcherModifier with optional initial modifier (may be nil).
|
||||
func newDispatcherModifier(modifier func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error)) *dispatcherModifier {
|
||||
dispatcherModifier := &dispatcherModifier{
|
||||
modifiers: make([]func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error), 0),
|
||||
}
|
||||
if modifier != nil {
|
||||
dispatcherModifier.QueueModifier(modifier)
|
||||
}
|
||||
return dispatcherModifier
|
||||
}
|
||||
|
||||
//QueueModifier queues up a new modifier
|
||||
func (c *dispatcherModifier) QueueModifier(modifier func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error)) {
|
||||
c.modifiers = append(c.modifiers, modifier)
|
||||
}
|
||||
|
||||
//Modify the provided HTTPRequestDispatcher with this modifier, and return the result, or error if something goes wrong
|
||||
func (c *dispatcherModifier) Modify(dispatcher common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error) {
|
||||
if len(c.modifiers) > 0 {
|
||||
for _, modifier := range c.modifiers {
|
||||
var err error
|
||||
if dispatcher, err = modifier(dispatcher); err != nil {
|
||||
common.Debugf("An error occurred when attempting to modify the dispatcher. Error was: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return dispatcher, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,569 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
// Package auth provides supporting functions and structs for authentication
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// federationClient is a client to retrieve the security token for an instance principal necessary to sign a request.
|
||||
// It also provides the private key whose corresponding public key is used to retrieve the security token.
|
||||
type federationClient interface {
|
||||
ClaimHolder
|
||||
PrivateKey() (*rsa.PrivateKey, error)
|
||||
SecurityToken() (string, error)
|
||||
}
|
||||
|
||||
// ClaimHolder is implemented by any token interface that provides access to the security claims embedded in the token.
|
||||
type ClaimHolder interface {
|
||||
GetClaim(key string) (interface{}, error)
|
||||
}
|
||||
|
||||
type genericFederationClient struct {
|
||||
SessionKeySupplier sessionKeySupplier
|
||||
RefreshSecurityToken func() (securityToken, error)
|
||||
|
||||
securityToken securityToken
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
var _ federationClient = &genericFederationClient{}
|
||||
|
||||
func (c *genericFederationClient) PrivateKey() (*rsa.PrivateKey, error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err := c.renewKeyAndSecurityTokenIfNotValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.SessionKeySupplier.PrivateKey(), nil
|
||||
}
|
||||
|
||||
func (c *genericFederationClient) SecurityToken() (token string, err error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err = c.renewKeyAndSecurityTokenIfNotValid(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return c.securityToken.String(), nil
|
||||
}
|
||||
|
||||
func (c *genericFederationClient) renewKeyAndSecurityTokenIfNotValid() (err error) {
|
||||
if c.securityToken == nil || !c.securityToken.Valid() {
|
||||
if err = c.renewKeyAndSecurityToken(); err != nil {
|
||||
return fmt.Errorf("failed to renew security token: %s", err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *genericFederationClient) renewKeyAndSecurityToken() (err error) {
|
||||
common.Logf("Renewing keys for file based security token at: %v\n", time.Now().Format("15:04:05.000"))
|
||||
if err = c.SessionKeySupplier.Refresh(); err != nil {
|
||||
return fmt.Errorf("failed to refresh session key: %s", err.Error())
|
||||
}
|
||||
|
||||
common.Logf("Renewing security token at: %v\n", time.Now().Format("15:04:05.000"))
|
||||
if c.securityToken, err = c.RefreshSecurityToken(); err != nil {
|
||||
return fmt.Errorf("failed to refresh security token key: %s", err.Error())
|
||||
}
|
||||
common.Logf("Security token renewed at: %v\n", time.Now().Format("15:04:05.000"))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *genericFederationClient) GetClaim(key string) (interface{}, error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err := c.renewKeyAndSecurityTokenIfNotValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.securityToken.GetClaim(key)
|
||||
}
|
||||
|
||||
func newFileBasedFederationClient(securityTokenPath string, supplier sessionKeySupplier) (*genericFederationClient, error) {
|
||||
return &genericFederationClient{
|
||||
SessionKeySupplier: supplier,
|
||||
RefreshSecurityToken: func() (token securityToken, err error) {
|
||||
var content []byte
|
||||
if content, err = ioutil.ReadFile(securityTokenPath); err != nil {
|
||||
return nil, fmt.Errorf("failed to read security token from :%s. Due to: %s", securityTokenPath, err.Error())
|
||||
}
|
||||
|
||||
var newToken securityToken
|
||||
if newToken, err = newPrincipalToken(string(content)); err != nil {
|
||||
return nil, fmt.Errorf("failed to read security token from :%s. Due to: %s", securityTokenPath, err.Error())
|
||||
}
|
||||
|
||||
return newToken, nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newStaticFederationClient(sessionToken string, supplier sessionKeySupplier) (*genericFederationClient, error) {
|
||||
var newToken securityToken
|
||||
var err error
|
||||
if newToken, err = newPrincipalToken(string(sessionToken)); err != nil {
|
||||
return nil, fmt.Errorf("failed to read security token. Due to: %s", err.Error())
|
||||
}
|
||||
|
||||
return &genericFederationClient{
|
||||
SessionKeySupplier: supplier,
|
||||
RefreshSecurityToken: func() (token securityToken, err error) {
|
||||
return newToken, nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// x509FederationClient retrieves a security token from Auth service.
|
||||
type x509FederationClient struct {
|
||||
tenancyID string
|
||||
sessionKeySupplier sessionKeySupplier
|
||||
leafCertificateRetriever x509CertificateRetriever
|
||||
intermediateCertificateRetrievers []x509CertificateRetriever
|
||||
securityToken securityToken
|
||||
authClient *common.BaseClient
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
func newX509FederationClient(region common.Region, tenancyID string, leafCertificateRetriever x509CertificateRetriever, intermediateCertificateRetrievers []x509CertificateRetriever, modifier dispatcherModifier) (federationClient, error) {
|
||||
client := &x509FederationClient{
|
||||
tenancyID: tenancyID,
|
||||
leafCertificateRetriever: leafCertificateRetriever,
|
||||
intermediateCertificateRetrievers: intermediateCertificateRetrievers,
|
||||
}
|
||||
client.sessionKeySupplier = newSessionKeySupplier()
|
||||
authClient := newAuthClient(region, client)
|
||||
|
||||
var err error
|
||||
|
||||
if authClient.HTTPClient, err = modifier.Modify(authClient.HTTPClient); err != nil {
|
||||
err = fmt.Errorf("failed to modify client: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.authClient = authClient
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func newX509FederationClientWithCerts(region common.Region, tenancyID string, leafCertificate, leafPassphrase, leafPrivateKey []byte, intermediateCertificates [][]byte, modifier dispatcherModifier) (federationClient, error) {
|
||||
intermediateRetrievers := make([]x509CertificateRetriever, len(intermediateCertificates))
|
||||
for i, c := range intermediateCertificates {
|
||||
intermediateRetrievers[i] = &staticCertificateRetriever{Passphrase: []byte(""), CertificatePem: c, PrivateKeyPem: nil}
|
||||
}
|
||||
|
||||
client := &x509FederationClient{
|
||||
tenancyID: tenancyID,
|
||||
leafCertificateRetriever: &staticCertificateRetriever{Passphrase: leafPassphrase, CertificatePem: leafCertificate, PrivateKeyPem: leafPrivateKey},
|
||||
intermediateCertificateRetrievers: intermediateRetrievers,
|
||||
}
|
||||
client.sessionKeySupplier = newSessionKeySupplier()
|
||||
authClient := newAuthClient(region, client)
|
||||
|
||||
var err error
|
||||
|
||||
if authClient.HTTPClient, err = modifier.Modify(authClient.HTTPClient); err != nil {
|
||||
err = fmt.Errorf("failed to modify client: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client.authClient = authClient
|
||||
return client, nil
|
||||
}
|
||||
|
||||
var (
|
||||
genericHeaders = []string{"date", "(request-target)"} // "host" is not needed for the federation endpoint. Don't ask me why.
|
||||
bodyHeaders = []string{"content-length", "content-type", "x-content-sha256"}
|
||||
)
|
||||
|
||||
func newAuthClient(region common.Region, provider common.KeyProvider) *common.BaseClient {
|
||||
signer := common.RequestSigner(provider, genericHeaders, bodyHeaders)
|
||||
client := common.DefaultBaseClientWithSigner(signer)
|
||||
if regionURL, ok := os.LookupEnv("OCI_SDK_AUTH_CLIENT_REGION_URL"); ok {
|
||||
client.Host = regionURL
|
||||
} else {
|
||||
client.Host = region.Endpoint("auth")
|
||||
}
|
||||
client.BasePath = "v1/x509"
|
||||
return &client
|
||||
}
|
||||
|
||||
// For authClient to sign requests to X509 Federation Endpoint
|
||||
func (c *x509FederationClient) KeyID() (string, error) {
|
||||
tenancy := c.tenancyID
|
||||
fingerprint := fingerprint(c.leafCertificateRetriever.Certificate())
|
||||
return fmt.Sprintf("%s/fed-x509/%s", tenancy, fingerprint), nil
|
||||
}
|
||||
|
||||
// For authClient to sign requests to X509 Federation Endpoint
|
||||
func (c *x509FederationClient) PrivateRSAKey() (*rsa.PrivateKey, error) {
|
||||
key := c.leafCertificateRetriever.PrivateKey()
|
||||
if key == nil {
|
||||
return nil, fmt.Errorf("can not read private key from leaf certificate. Likely an error in the metadata service")
|
||||
}
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) PrivateKey() (*rsa.PrivateKey, error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err := c.renewSecurityTokenIfNotValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.sessionKeySupplier.PrivateKey(), nil
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) SecurityToken() (token string, err error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err = c.renewSecurityTokenIfNotValid(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return c.securityToken.String(), nil
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) renewSecurityTokenIfNotValid() (err error) {
|
||||
if c.securityToken == nil || !c.securityToken.Valid() {
|
||||
if err = c.renewSecurityToken(); err != nil {
|
||||
return fmt.Errorf("failed to renew security token: %s", err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) renewSecurityToken() (err error) {
|
||||
if err = c.sessionKeySupplier.Refresh(); err != nil {
|
||||
return fmt.Errorf("failed to refresh session key: %s", err.Error())
|
||||
}
|
||||
|
||||
if err = c.leafCertificateRetriever.Refresh(); err != nil {
|
||||
return fmt.Errorf("failed to refresh leaf certificate: %s", err.Error())
|
||||
}
|
||||
|
||||
updatedTenancyID := extractTenancyIDFromCertificate(c.leafCertificateRetriever.Certificate())
|
||||
if c.tenancyID != updatedTenancyID {
|
||||
err = fmt.Errorf("unexpected update of tenancy OCID in the leaf certificate. Previous tenancy: %s, Updated: %s", c.tenancyID, updatedTenancyID)
|
||||
return
|
||||
}
|
||||
|
||||
for _, retriever := range c.intermediateCertificateRetrievers {
|
||||
if err = retriever.Refresh(); err != nil {
|
||||
return fmt.Errorf("failed to refresh intermediate certificate: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
common.Logf("Renewing security token at: %v\n", time.Now().Format("15:04:05.000"))
|
||||
if c.securityToken, err = c.getSecurityToken(); err != nil {
|
||||
return fmt.Errorf("failed to get security token: %s", err.Error())
|
||||
}
|
||||
common.Logf("Security token renewed at: %v\n", time.Now().Format("15:04:05.000"))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) getSecurityToken() (securityToken, error) {
|
||||
request := c.makeX509FederationRequest()
|
||||
|
||||
var err error
|
||||
var httpRequest http.Request
|
||||
if httpRequest, err = common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost, "", request); err != nil {
|
||||
return nil, fmt.Errorf("failed to make http request: %s", err.Error())
|
||||
}
|
||||
|
||||
var httpResponse *http.Response
|
||||
defer common.CloseBodyIfValid(httpResponse)
|
||||
|
||||
for retry := 0; retry < 5; retry++ {
|
||||
if httpResponse, err = c.authClient.Call(context.Background(), &httpRequest); err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(250 * time.Microsecond)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to call: %s", err.Error())
|
||||
}
|
||||
|
||||
response := x509FederationResponse{}
|
||||
if err = common.UnmarshalResponse(httpResponse, &response); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal the response: %s", err.Error())
|
||||
}
|
||||
|
||||
return newPrincipalToken(response.Token.Token)
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) GetClaim(key string) (interface{}, error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err := c.renewSecurityTokenIfNotValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.securityToken.GetClaim(key)
|
||||
}
|
||||
|
||||
type x509FederationRequest struct {
|
||||
X509FederationDetails `contributesTo:"body"`
|
||||
}
|
||||
|
||||
// X509FederationDetails x509 federation details
|
||||
type X509FederationDetails struct {
|
||||
Certificate string `mandatory:"true" json:"certificate,omitempty"`
|
||||
PublicKey string `mandatory:"true" json:"publicKey,omitempty"`
|
||||
IntermediateCertificates []string `mandatory:"false" json:"intermediateCertificates,omitempty"`
|
||||
}
|
||||
|
||||
type x509FederationResponse struct {
|
||||
Token `presentIn:"body"`
|
||||
}
|
||||
|
||||
// Token token
|
||||
type Token struct {
|
||||
Token string `mandatory:"true" json:"token,omitempty"`
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) makeX509FederationRequest() *x509FederationRequest {
|
||||
certificate := c.sanitizeCertificateString(string(c.leafCertificateRetriever.CertificatePemRaw()))
|
||||
publicKey := c.sanitizeCertificateString(string(c.sessionKeySupplier.PublicKeyPemRaw()))
|
||||
var intermediateCertificates []string
|
||||
for _, retriever := range c.intermediateCertificateRetrievers {
|
||||
intermediateCertificates = append(intermediateCertificates, c.sanitizeCertificateString(string(retriever.CertificatePemRaw())))
|
||||
}
|
||||
|
||||
details := X509FederationDetails{
|
||||
Certificate: certificate,
|
||||
PublicKey: publicKey,
|
||||
IntermediateCertificates: intermediateCertificates,
|
||||
}
|
||||
return &x509FederationRequest{details}
|
||||
}
|
||||
|
||||
func (c *x509FederationClient) sanitizeCertificateString(certString string) string {
|
||||
certString = strings.Replace(certString, "-----BEGIN CERTIFICATE-----", "", -1)
|
||||
certString = strings.Replace(certString, "-----END CERTIFICATE-----", "", -1)
|
||||
certString = strings.Replace(certString, "-----BEGIN PUBLIC KEY-----", "", -1)
|
||||
certString = strings.Replace(certString, "-----END PUBLIC KEY-----", "", -1)
|
||||
certString = strings.Replace(certString, "\n", "", -1)
|
||||
return certString
|
||||
}
|
||||
|
||||
// sessionKeySupplier provides an RSA keypair which can be re-generated by calling Refresh().
|
||||
type sessionKeySupplier interface {
|
||||
Refresh() error
|
||||
PrivateKey() *rsa.PrivateKey
|
||||
PublicKeyPemRaw() []byte
|
||||
}
|
||||
|
||||
//genericKeySupplier implements sessionKeySupplier and provides an arbitrary refresh mechanism
|
||||
type genericKeySupplier struct {
|
||||
RefreshFn func() (*rsa.PrivateKey, []byte, error)
|
||||
|
||||
privateKey *rsa.PrivateKey
|
||||
publicKeyPemRaw []byte
|
||||
}
|
||||
|
||||
func (s genericKeySupplier) PrivateKey() *rsa.PrivateKey {
|
||||
if s.privateKey == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := *s.privateKey
|
||||
return &c
|
||||
}
|
||||
|
||||
func (s genericKeySupplier) PublicKeyPemRaw() []byte {
|
||||
if s.publicKeyPemRaw == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]byte, len(s.publicKeyPemRaw))
|
||||
copy(c, s.publicKeyPemRaw)
|
||||
return c
|
||||
}
|
||||
|
||||
func (s *genericKeySupplier) Refresh() (err error) {
|
||||
privateKey, publicPem, err := s.RefreshFn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.privateKey = privateKey
|
||||
s.publicKeyPemRaw = publicPem
|
||||
return nil
|
||||
}
|
||||
|
||||
// create a sessionKeySupplier that reads keys from file every time it refreshes
|
||||
func newFileBasedKeySessionSupplier(privateKeyPemPath string, passphrasePath *string) (*genericKeySupplier, error) {
|
||||
return &genericKeySupplier{
|
||||
RefreshFn: func() (*rsa.PrivateKey, []byte, error) {
|
||||
var err error
|
||||
var passContent []byte
|
||||
if passphrasePath != nil {
|
||||
if passContent, err = ioutil.ReadFile(*passphrasePath); err != nil {
|
||||
return nil, nil, fmt.Errorf("can not read passphrase from file: %s, due to %s", *passphrasePath, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
var keyPemContent []byte
|
||||
if keyPemContent, err = ioutil.ReadFile(privateKeyPemPath); err != nil {
|
||||
return nil, nil, fmt.Errorf("can not read private privateKey pem from file: %s, due to %s", privateKeyPemPath, err.Error())
|
||||
}
|
||||
|
||||
var privateKey *rsa.PrivateKey
|
||||
if privateKey, err = common.PrivateKeyFromBytesWithPassword(keyPemContent, passContent); err != nil {
|
||||
return nil, nil, fmt.Errorf("can not create private privateKey from contents of: %s, due to: %s", privateKeyPemPath, err.Error())
|
||||
}
|
||||
|
||||
var publicKeyAsnBytes []byte
|
||||
if publicKeyAsnBytes, err = x509.MarshalPKIXPublicKey(privateKey.Public()); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to marshal the public part of the new keypair: %s", err.Error())
|
||||
}
|
||||
publicKeyPemRaw := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: publicKeyAsnBytes,
|
||||
})
|
||||
return privateKey, publicKeyPemRaw, nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func newStaticKeySessionSupplier(privateKeyPemContent, passphrase []byte) (*genericKeySupplier, error) {
|
||||
var err error
|
||||
var privateKey *rsa.PrivateKey
|
||||
|
||||
if privateKey, err = common.PrivateKeyFromBytesWithPassword(privateKeyPemContent, passphrase); err != nil {
|
||||
return nil, fmt.Errorf("can not create private privateKey, due to: %s", err.Error())
|
||||
}
|
||||
|
||||
var publicKeyAsnBytes []byte
|
||||
if publicKeyAsnBytes, err = x509.MarshalPKIXPublicKey(privateKey.Public()); err != nil {
|
||||
return nil, fmt.Errorf("failed to marshal the public part of the new keypair: %s", err.Error())
|
||||
}
|
||||
publicKeyPemRaw := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: publicKeyAsnBytes,
|
||||
})
|
||||
|
||||
return &genericKeySupplier{
|
||||
RefreshFn: func() (key *rsa.PrivateKey, bytes []byte, err error) {
|
||||
return privateKey, publicKeyPemRaw, nil
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// inMemorySessionKeySupplier implements sessionKeySupplier to vend an RSA keypair.
|
||||
// Refresh() generates a new RSA keypair with a random source, and keeps it in memory.
|
||||
//
|
||||
// inMemorySessionKeySupplier is not thread-safe.
|
||||
type inMemorySessionKeySupplier struct {
|
||||
keySize int
|
||||
privateKey *rsa.PrivateKey
|
||||
publicKeyPemRaw []byte
|
||||
}
|
||||
|
||||
// newSessionKeySupplier creates and returns a sessionKeySupplier instance which generates key pairs of size 2048.
|
||||
func newSessionKeySupplier() sessionKeySupplier {
|
||||
return &inMemorySessionKeySupplier{keySize: 2048}
|
||||
}
|
||||
|
||||
// Refresh() is failure atomic, i.e., PrivateKey() and PublicKeyPemRaw() would return their previous values
|
||||
// if Refresh() fails.
|
||||
func (s *inMemorySessionKeySupplier) Refresh() (err error) {
|
||||
common.Debugln("Refreshing session key")
|
||||
|
||||
var privateKey *rsa.PrivateKey
|
||||
privateKey, err = rsa.GenerateKey(rand.Reader, s.keySize)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate a new keypair: %s", err)
|
||||
}
|
||||
|
||||
var publicKeyAsnBytes []byte
|
||||
if publicKeyAsnBytes, err = x509.MarshalPKIXPublicKey(privateKey.Public()); err != nil {
|
||||
return fmt.Errorf("failed to marshal the public part of the new keypair: %s", err.Error())
|
||||
}
|
||||
publicKeyPemRaw := pem.EncodeToMemory(&pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: publicKeyAsnBytes,
|
||||
})
|
||||
|
||||
s.privateKey = privateKey
|
||||
s.publicKeyPemRaw = publicKeyPemRaw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *inMemorySessionKeySupplier) PrivateKey() *rsa.PrivateKey {
|
||||
if s.privateKey == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := *s.privateKey
|
||||
return &c
|
||||
}
|
||||
|
||||
func (s *inMemorySessionKeySupplier) PublicKeyPemRaw() []byte {
|
||||
if s.publicKeyPemRaw == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
c := make([]byte, len(s.publicKeyPemRaw))
|
||||
copy(c, s.publicKeyPemRaw)
|
||||
return c
|
||||
}
|
||||
|
||||
type securityToken interface {
|
||||
fmt.Stringer
|
||||
Valid() bool
|
||||
|
||||
ClaimHolder
|
||||
}
|
||||
|
||||
type principalToken struct {
|
||||
tokenString string
|
||||
jwtToken *jwtToken
|
||||
}
|
||||
|
||||
func newPrincipalToken(tokenString string) (newToken securityToken, err error) {
|
||||
var jwtToken *jwtToken
|
||||
if jwtToken, err = parseJwt(tokenString); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse the token string \"%s\": %s", tokenString, err.Error())
|
||||
}
|
||||
return &principalToken{tokenString, jwtToken}, nil
|
||||
}
|
||||
|
||||
func (t *principalToken) String() string {
|
||||
return t.tokenString
|
||||
}
|
||||
|
||||
func (t *principalToken) Valid() bool {
|
||||
return !t.jwtToken.expired()
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrNoSuchClaim is returned when a token does not hold the claim sought
|
||||
ErrNoSuchClaim = errors.New("no such claim")
|
||||
)
|
||||
|
||||
func (t *principalToken) GetClaim(key string) (interface{}, error) {
|
||||
if value, ok := t.jwtToken.payload[key]; ok {
|
||||
return value, nil
|
||||
}
|
||||
return nil, ErrNoSuchClaim
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
type instancePrincipalDelegationTokenConfigurationProvider struct {
|
||||
instancePrincipalKeyProvider instancePrincipalKeyProvider
|
||||
delegationToken string
|
||||
}
|
||||
|
||||
//InstancePrincipalDelegationTokenConfigurationProvider returns a configuration for obo token instance principals
|
||||
func InstancePrincipalDelegationTokenConfigurationProvider(delegationToken *string) (common.ConfigurationProvider, error) {
|
||||
if delegationToken == nil || len(*delegationToken) == 0 {
|
||||
return nil, fmt.Errorf("failed to create a delagationTokenConfigurationProvider: token is a mondatory input paras")
|
||||
}
|
||||
return newInstancePrincipalDelegationTokenConfigurationProvider(delegationToken, nil)
|
||||
}
|
||||
|
||||
func newInstancePrincipalDelegationTokenConfigurationProvider(delegationToken *string, modifier func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher,
|
||||
error)) (common.ConfigurationProvider, error) {
|
||||
|
||||
keyProvider, err := newInstancePrincipalKeyProvider(modifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create a new key provider for instance principal: %s", err.Error())
|
||||
}
|
||||
return instancePrincipalDelegationTokenConfigurationProvider{*keyProvider, *delegationToken}, err
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) getInstancePrincipalDelegationTokenConfigurationProvider() (instancePrincipalDelegationTokenConfigurationProvider, error) {
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) PrivateRSAKey() (*rsa.PrivateKey, error) {
|
||||
return p.instancePrincipalKeyProvider.PrivateRSAKey()
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) KeyID() (string, error) {
|
||||
return p.instancePrincipalKeyProvider.KeyID()
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) TenancyOCID() (string, error) {
|
||||
return p.instancePrincipalKeyProvider.TenancyOCID()
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) UserOCID() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) KeyFingerprint() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) Region() (string, error) {
|
||||
region := p.instancePrincipalKeyProvider.RegionForFederationClient()
|
||||
return string(region), nil
|
||||
}
|
||||
|
||||
func (p instancePrincipalDelegationTokenConfigurationProvider) AuthType() (common.AuthConfig, error) {
|
||||
token := p.delegationToken
|
||||
return common.AuthConfig{common.InstancePrincipalDelegationToken, false, &token}, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
const (
|
||||
metadataBaseURL = `http://169.254.169.254/opc/v2`
|
||||
metadataFallbackURL = `http://169.254.169.254/opc/v1`
|
||||
regionPath = `/instance/region`
|
||||
leafCertificatePath = `/identity/cert.pem`
|
||||
leafCertificateKeyPath = `/identity/key.pem`
|
||||
intermediateCertificatePath = `/identity/intermediate.pem`
|
||||
|
||||
leafCertificateKeyPassphrase = `` // No passphrase for the private key for Compute instances
|
||||
intermediateCertificateKeyURL = ``
|
||||
intermediateCertificateKeyPassphrase = `` // No passphrase for the private key for Compute instances
|
||||
)
|
||||
|
||||
var (
|
||||
regionURL, leafCertificateURL, leafCertificateKeyURL, intermediateCertificateURL string
|
||||
)
|
||||
|
||||
// instancePrincipalKeyProvider implements KeyProvider to provide a key ID and its corresponding private key
|
||||
// for an instance principal by getting a security token via x509FederationClient.
|
||||
//
|
||||
// The region name of the endpoint for x509FederationClient is obtained from the metadata service on the compute
|
||||
// instance.
|
||||
type instancePrincipalKeyProvider struct {
|
||||
Region common.Region
|
||||
FederationClient federationClient
|
||||
TenancyID string
|
||||
}
|
||||
|
||||
// newInstancePrincipalKeyProvider creates and returns an instancePrincipalKeyProvider instance based on
|
||||
// x509FederationClient.
|
||||
//
|
||||
// NOTE: There is a race condition between PrivateRSAKey() and KeyID(). These two pieces are tightly coupled; KeyID
|
||||
// includes a security token obtained from Auth service by giving a public key which is paired with PrivateRSAKey.
|
||||
// The x509FederationClient caches the security token in memory until it is expired. Thus, even if a client obtains a
|
||||
// KeyID that is not expired at the moment, the PrivateRSAKey that the client acquires at a next moment could be
|
||||
// invalid because the KeyID could be already expired.
|
||||
func newInstancePrincipalKeyProvider(modifier func(common.HTTPRequestDispatcher) (common.HTTPRequestDispatcher, error)) (provider *instancePrincipalKeyProvider, err error) {
|
||||
updateX509CertRetrieverURLParas(metadataBaseURL)
|
||||
clientModifier := newDispatcherModifier(modifier)
|
||||
|
||||
client, err := clientModifier.Modify(&http.Client{})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to modify client: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var region common.Region
|
||||
|
||||
if region, err = getRegionForFederationClient(client, regionURL); err != nil {
|
||||
err = fmt.Errorf("failed to get the region name from %s: %s", regionURL, err.Error())
|
||||
common.Logf("%v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
leafCertificateRetriever := newURLBasedX509CertificateRetriever(client,
|
||||
leafCertificateURL, leafCertificateKeyURL, leafCertificateKeyPassphrase)
|
||||
intermediateCertificateRetrievers := []x509CertificateRetriever{
|
||||
newURLBasedX509CertificateRetriever(
|
||||
client, intermediateCertificateURL, intermediateCertificateKeyURL,
|
||||
intermediateCertificateKeyPassphrase),
|
||||
}
|
||||
|
||||
if err = leafCertificateRetriever.Refresh(); err != nil {
|
||||
err = fmt.Errorf("failed to refresh the leaf certificate: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
tenancyID := extractTenancyIDFromCertificate(leafCertificateRetriever.Certificate())
|
||||
|
||||
federationClient, err := newX509FederationClient(region, tenancyID, leafCertificateRetriever, intermediateCertificateRetrievers, *clientModifier)
|
||||
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to create federation client: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provider = &instancePrincipalKeyProvider{FederationClient: federationClient, TenancyID: tenancyID, Region: region}
|
||||
return
|
||||
}
|
||||
|
||||
func getRegionForFederationClient(dispatcher common.HTTPRequestDispatcher, url string) (r common.Region, err error) {
|
||||
var body bytes.Buffer
|
||||
var statusCode int
|
||||
MaxRetriesFederationClient := 3
|
||||
for currTry := 0; currTry < MaxRetriesFederationClient; currTry++ {
|
||||
body, statusCode, err = httpGet(dispatcher, url)
|
||||
if err == nil && statusCode == 200 {
|
||||
return common.StringToRegion(body.String()), nil
|
||||
}
|
||||
common.Logf("Error in getting region from url: %s, Status code: %v, Error: %s", url, statusCode, err.Error())
|
||||
if statusCode == 404 && strings.Compare(url, metadataBaseURL+regionPath) == 0 {
|
||||
common.Logf("Falling back to http://169.254.169.254/opc/v1 to try again...")
|
||||
updateX509CertRetrieverURLParas(metadataFallbackURL)
|
||||
url = regionURL
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func updateX509CertRetrieverURLParas(baseURL string) {
|
||||
regionURL = baseURL + regionPath
|
||||
leafCertificateURL = baseURL + leafCertificatePath
|
||||
leafCertificateKeyURL = baseURL + leafCertificateKeyPath
|
||||
intermediateCertificateURL = baseURL + intermediateCertificatePath
|
||||
}
|
||||
|
||||
func (p *instancePrincipalKeyProvider) RegionForFederationClient() common.Region {
|
||||
return p.Region
|
||||
}
|
||||
|
||||
func (p *instancePrincipalKeyProvider) PrivateRSAKey() (privateKey *rsa.PrivateKey, err error) {
|
||||
if privateKey, err = p.FederationClient.PrivateKey(); err != nil {
|
||||
err = fmt.Errorf("failed to get private key: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
func (p *instancePrincipalKeyProvider) KeyID() (string, error) {
|
||||
var securityToken string
|
||||
var err error
|
||||
if securityToken, err = p.FederationClient.SecurityToken(); err != nil {
|
||||
return "", fmt.Errorf("failed to get security token: %s", err.Error())
|
||||
}
|
||||
return fmt.Sprintf("ST$%s", securityToken), nil
|
||||
}
|
||||
|
||||
func (p *instancePrincipalKeyProvider) TenancyOCID() (string, error) {
|
||||
return p.TenancyID, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type jwtToken struct {
|
||||
raw string
|
||||
header map[string]interface{}
|
||||
payload map[string]interface{}
|
||||
}
|
||||
|
||||
const bufferTimeBeforeTokenExpiration = 5 * time.Minute
|
||||
|
||||
func (t *jwtToken) expired() bool {
|
||||
exp := int64(t.payload["exp"].(float64))
|
||||
expTime := time.Unix(exp, 0)
|
||||
expired := exp <= time.Now().Unix()+int64(bufferTimeBeforeTokenExpiration.Seconds())
|
||||
if expired {
|
||||
common.Debugf("Token expires at: %v, currently expired due to bufferTime: %v", expTime.Format("15:04:05.000"), expired)
|
||||
}
|
||||
return expired
|
||||
}
|
||||
|
||||
func parseJwt(tokenString string) (*jwtToken, error) {
|
||||
parts := strings.Split(tokenString, ".")
|
||||
if len(parts) != 3 {
|
||||
return nil, fmt.Errorf("the given token string contains an invalid number of parts")
|
||||
}
|
||||
|
||||
token := &jwtToken{raw: tokenString}
|
||||
var err error
|
||||
|
||||
// Parse Header part
|
||||
var headerBytes []byte
|
||||
if headerBytes, err = decodePart(parts[0]); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode the header bytes: %s", err.Error())
|
||||
}
|
||||
if err = json.Unmarshal(headerBytes, &token.header); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Parse Payload part
|
||||
var payloadBytes []byte
|
||||
if payloadBytes, err = decodePart(parts[1]); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode the payload bytes: %s", err.Error())
|
||||
}
|
||||
decoder := json.NewDecoder(bytes.NewBuffer(payloadBytes))
|
||||
if err = decoder.Decode(&token.payload); err != nil {
|
||||
return nil, fmt.Errorf("failed to decode the payload json: %s", err.Error())
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func decodePart(partString string) ([]byte, error) {
|
||||
if l := len(partString) % 4; 0 < l {
|
||||
partString += strings.Repeat("=", 4-l)
|
||||
}
|
||||
return base64.URLEncoding.DecodeString(partString)
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
const (
|
||||
//ResourcePrincipalVersion2_2 is a supported version for resource principals
|
||||
ResourcePrincipalVersion2_2 = "2.2"
|
||||
//ResourcePrincipalVersionEnvVar environment var name for version
|
||||
ResourcePrincipalVersionEnvVar = "OCI_RESOURCE_PRINCIPAL_VERSION"
|
||||
//ResourcePrincipalRPSTEnvVar environment var name holding the token or a path to the token
|
||||
ResourcePrincipalRPSTEnvVar = "OCI_RESOURCE_PRINCIPAL_RPST"
|
||||
//ResourcePrincipalPrivatePEMEnvVar environment var holding a rsa private key in pem format or a path to one
|
||||
ResourcePrincipalPrivatePEMEnvVar = "OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM"
|
||||
//ResourcePrincipalPrivatePEMPassphraseEnvVar environment var holding the passphrase to a key or a path to one
|
||||
ResourcePrincipalPrivatePEMPassphraseEnvVar = "OCI_RESOURCE_PRINCIPAL_PRIVATE_PEM_PASSPHRASE"
|
||||
//ResourcePrincipalRegionEnvVar environment variable holding a region
|
||||
ResourcePrincipalRegionEnvVar = "OCI_RESOURCE_PRINCIPAL_REGION"
|
||||
|
||||
//ResourcePrincipalVersion1_1 is a supported version for resource principals
|
||||
ResourcePrincipalVersion1_1 = "1.1"
|
||||
//ResourcePrincipalSessionTokenEndpoint endpoint for retrieving the Resource Principal Session Token
|
||||
ResourcePrincipalSessionTokenEndpoint = "OCI_RESOURCE_PRINCIPAL_RPST_ENDPOINT"
|
||||
//ResourcePrincipalTokenEndpoint endpoint for retrieving the Resource Principal Token
|
||||
ResourcePrincipalTokenEndpoint = "OCI_RESOURCE_PRINCIPAL_RPT_ENDPOINT"
|
||||
|
||||
// TenancyOCIDClaimKey is the key used to look up the resource tenancy in an RPST
|
||||
TenancyOCIDClaimKey = "res_tenant"
|
||||
// CompartmentOCIDClaimKey is the key used to look up the resource compartment in an RPST
|
||||
CompartmentOCIDClaimKey = "res_compartment"
|
||||
)
|
||||
|
||||
// ConfigurationProviderWithClaimAccess mixes in a method to access the claims held on the underlying security token
|
||||
type ConfigurationProviderWithClaimAccess interface {
|
||||
common.ConfigurationProvider
|
||||
ClaimHolder
|
||||
}
|
||||
|
||||
// ResourcePrincipalConfigurationProvider returns a resource principal configuration provider using well known
|
||||
// environment variables to look up token information. The environment variables can either paths or contain the material value
|
||||
// of the keys. However in the case of the keys and tokens paths and values can not be mixed
|
||||
func ResourcePrincipalConfigurationProvider() (ConfigurationProviderWithClaimAccess, error) {
|
||||
var version string
|
||||
var ok bool
|
||||
if version, ok = os.LookupEnv(ResourcePrincipalVersionEnvVar); !ok {
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, not present", ResourcePrincipalVersionEnvVar)
|
||||
}
|
||||
|
||||
switch version {
|
||||
case ResourcePrincipalVersion2_2:
|
||||
rpst := requireEnv(ResourcePrincipalRPSTEnvVar)
|
||||
if rpst == nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, not present", ResourcePrincipalRPSTEnvVar)
|
||||
}
|
||||
private := requireEnv(ResourcePrincipalPrivatePEMEnvVar)
|
||||
if private == nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, not present", ResourcePrincipalPrivatePEMEnvVar)
|
||||
}
|
||||
passphrase := requireEnv(ResourcePrincipalPrivatePEMPassphraseEnvVar)
|
||||
region := requireEnv(ResourcePrincipalRegionEnvVar)
|
||||
if region == nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, not present", ResourcePrincipalRegionEnvVar)
|
||||
}
|
||||
return newResourcePrincipalKeyProvider22(
|
||||
*rpst, *private, passphrase, *region)
|
||||
case ResourcePrincipalVersion1_1:
|
||||
return newResourcePrincipalKeyProvider11(DefaultRptPathProvider{})
|
||||
default:
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, must be valid", ResourcePrincipalVersionEnvVar)
|
||||
}
|
||||
}
|
||||
|
||||
// ResourcePrincipalConfigurationProviderWithPathProvider returns a resource principal configuration provider using path provider.
|
||||
func ResourcePrincipalConfigurationProviderWithPathProvider(pathProvider PathProvider) (ConfigurationProviderWithClaimAccess, error) {
|
||||
var version string
|
||||
var ok bool
|
||||
if version, ok = os.LookupEnv(ResourcePrincipalVersionEnvVar); !ok {
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, not present", ResourcePrincipalVersionEnvVar)
|
||||
} else if version != ResourcePrincipalVersion1_1 {
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, must be %s", ResourcePrincipalVersionEnvVar, ResourcePrincipalVersion1_1)
|
||||
}
|
||||
return newResourcePrincipalKeyProvider11(pathProvider)
|
||||
}
|
||||
|
||||
func newResourcePrincipalKeyProvider11(pathProvider PathProvider) (ConfigurationProviderWithClaimAccess, error) {
|
||||
rptEndpoint := requireEnv(ResourcePrincipalTokenEndpoint)
|
||||
if rptEndpoint == nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, environment variable: %s, not present", ResourcePrincipalTokenEndpoint)
|
||||
}
|
||||
rptPath, err := pathProvider.Path()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, due to: %s ", err.Error())
|
||||
}
|
||||
resourceID, err := pathProvider.ResourceID()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, due to: %s ", err.Error())
|
||||
}
|
||||
rp, err := resourcePrincipalConfigurationProviderV1(*rptEndpoint+*rptPath, *resourceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, due to: %s ", err.Error())
|
||||
}
|
||||
return rp, nil
|
||||
}
|
||||
|
||||
func requireEnv(key string) *string {
|
||||
if val, ok := os.LookupEnv(key); ok {
|
||||
return &val
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// resourcePrincipalKeyProvider22 is key provider that reads from specified the specified environment variables
|
||||
// the environment variables can host the material keys/passphrases or they can be paths to files that need to be read
|
||||
type resourcePrincipalKeyProvider struct {
|
||||
FederationClient federationClient
|
||||
KeyProviderRegion common.Region
|
||||
}
|
||||
|
||||
func newResourcePrincipalKeyProvider22(sessionTokenLocation, privatePemLocation string,
|
||||
passphraseLocation *string, region string) (*resourcePrincipalKeyProvider, error) {
|
||||
|
||||
//Check both the the passphrase and the key are paths
|
||||
if passphraseLocation != nil && (!isPath(privatePemLocation) && isPath(*passphraseLocation) ||
|
||||
isPath(privatePemLocation) && !isPath(*passphraseLocation)) {
|
||||
return nil, fmt.Errorf("cant not create resource principal: both key and passphrase need to be path or none needs to be path")
|
||||
}
|
||||
|
||||
var supplier sessionKeySupplier
|
||||
var err error
|
||||
|
||||
//File based case
|
||||
if isPath(privatePemLocation) {
|
||||
supplier, err = newFileBasedKeySessionSupplier(privatePemLocation, passphraseLocation)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, due to: %s ", err.Error())
|
||||
}
|
||||
} else {
|
||||
//else the content is in the env vars
|
||||
var passphrase []byte
|
||||
if passphraseLocation != nil {
|
||||
passphrase = []byte(*passphraseLocation)
|
||||
}
|
||||
supplier, err = newStaticKeySessionSupplier([]byte(privatePemLocation), passphrase)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, due to: %s ", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
var fd federationClient
|
||||
if isPath(sessionTokenLocation) {
|
||||
fd, _ = newFileBasedFederationClient(sessionTokenLocation, supplier)
|
||||
} else {
|
||||
fd, err = newStaticFederationClient(sessionTokenLocation, supplier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can not create resource principal, due to: %s ", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
rs := resourcePrincipalKeyProvider{
|
||||
FederationClient: fd,
|
||||
KeyProviderRegion: common.StringToRegion(region),
|
||||
}
|
||||
return &rs, nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) PrivateRSAKey() (privateKey *rsa.PrivateKey, err error) {
|
||||
if privateKey, err = p.FederationClient.PrivateKey(); err != nil {
|
||||
err = fmt.Errorf("failed to get private key: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) KeyID() (string, error) {
|
||||
var securityToken string
|
||||
var err error
|
||||
if securityToken, err = p.FederationClient.SecurityToken(); err != nil {
|
||||
return "", fmt.Errorf("failed to get security token: %s", err.Error())
|
||||
}
|
||||
return fmt.Sprintf("ST$%s", securityToken), nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) Region() (string, error) {
|
||||
return string(p.KeyProviderRegion), nil
|
||||
}
|
||||
|
||||
var (
|
||||
// ErrNonStringClaim is returned if the token has a claim for a key, but it's not a string value
|
||||
ErrNonStringClaim = errors.New("claim does not have a string value")
|
||||
)
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) TenancyOCID() (string, error) {
|
||||
if claim, err := p.GetClaim(TenancyOCIDClaimKey); err != nil {
|
||||
return "", err
|
||||
} else if tenancy, ok := claim.(string); ok {
|
||||
return tenancy, nil
|
||||
} else {
|
||||
return "", ErrNonStringClaim
|
||||
}
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) GetClaim(claim string) (interface{}, error) {
|
||||
return p.FederationClient.GetClaim(claim)
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) KeyFingerprint() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) UserOCID() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalKeyProvider) AuthType() (common.AuthConfig, error) {
|
||||
return common.AuthConfig{common.UnknownAuthenticationType, false, nil}, fmt.Errorf("unsupported, keep the interface")
|
||||
}
|
||||
|
||||
// By contract for the the content of a resource principal to be considered path, it needs to be
|
||||
// an absolute path.
|
||||
func isPath(str string) bool {
|
||||
return path.IsAbs(str)
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
imdsPathTemplate = "/20180711/resourcePrincipalToken/{id}"
|
||||
instanceIDURL = `http://169.254.169.254/opc/v2/instance/id`
|
||||
|
||||
//ResourcePrincipalTokenPath path for retrieving the Resource Principal Token
|
||||
ResourcePrincipalTokenPath = "OCI_RESOURCE_PRINCIPAL_RPT_PATH"
|
||||
//ResourceID OCID for the resource for Resource Principal
|
||||
ResourceID = "OCI_RESOURCE_PRINCIPAL_RPT_ID"
|
||||
)
|
||||
|
||||
// PathProvider is an interface that returns path and resource ID
|
||||
type PathProvider interface {
|
||||
Path() (*string, error)
|
||||
ResourceID() (*string, error)
|
||||
}
|
||||
|
||||
// StringRptPathProvider is a simple path provider that takes a string and returns it
|
||||
type StringRptPathProvider struct {
|
||||
path string
|
||||
resourceID string
|
||||
}
|
||||
|
||||
// Path returns the resource principal token path
|
||||
func (pp StringRptPathProvider) Path() (*string, error) {
|
||||
return &pp.path, nil
|
||||
}
|
||||
|
||||
// ResourceID returns the resource associated with the resource principal
|
||||
func (pp StringRptPathProvider) ResourceID() (*string, error) {
|
||||
return &pp.resourceID, nil
|
||||
}
|
||||
|
||||
// ImdsRptPathProvider sets the path from a default value and the resource ID from instance metadata
|
||||
type ImdsRptPathProvider struct{}
|
||||
|
||||
// Path returns the resource principal token path
|
||||
func (pp ImdsRptPathProvider) Path() (*string, error) {
|
||||
path := imdsPathTemplate
|
||||
return &path, nil
|
||||
}
|
||||
|
||||
// ResourceID returns the resource associated with the resource principal
|
||||
func (pp ImdsRptPathProvider) ResourceID() (*string, error) {
|
||||
instanceID, err := getInstanceIDFromMetadata()
|
||||
return &instanceID, err
|
||||
}
|
||||
|
||||
// EnvRptPathProvider sets the path and resource ID from environment variables
|
||||
type EnvRptPathProvider struct{}
|
||||
|
||||
// Path returns the resource principal token path
|
||||
func (pp EnvRptPathProvider) Path() (*string, error) {
|
||||
path := requireEnv(ResourcePrincipalTokenPath)
|
||||
if path == nil {
|
||||
return nil, fmt.Errorf("missing %s env var", ResourcePrincipalTokenPath)
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
||||
// ResourceID returns the resource associated with the resource principal
|
||||
func (pp EnvRptPathProvider) ResourceID() (*string, error) {
|
||||
rpID := requireEnv(ResourceID)
|
||||
if rpID == nil {
|
||||
return nil, fmt.Errorf("missing %s env var", ResourceID)
|
||||
}
|
||||
return rpID, nil
|
||||
}
|
||||
|
||||
//DefaultRptPathProvider path provider makes sure the behavior happens with the correct fallback.
|
||||
//
|
||||
//For the path,
|
||||
//Use the contents of the OCI_RESOURCE_PRINCIPAL_RPT_PATH environment variable, if set.
|
||||
//Otherwise, use the current path: "/20180711/resourcePrincipalToken/{id}"
|
||||
//
|
||||
//For the resource id,
|
||||
//Use the contents of the OCI_RESOURCE_PRINCIPAL_RPT_ID environment variable, if set.
|
||||
//Otherwise, use IMDS to get the instance id
|
||||
//
|
||||
//This path provider is used when the caller doesn't provide a specific path provider to the resource principals signer
|
||||
type DefaultRptPathProvider struct {
|
||||
path string
|
||||
resourceID string
|
||||
}
|
||||
|
||||
// Path returns the resource principal token path
|
||||
func (pp DefaultRptPathProvider) Path() (*string, error) {
|
||||
path := requireEnv(ResourcePrincipalTokenPath)
|
||||
if path == nil {
|
||||
rpPath := imdsPathTemplate
|
||||
return &rpPath, nil
|
||||
}
|
||||
return path, nil
|
||||
}
|
||||
|
||||
// ResourceID returns the resource associated with the resource principal
|
||||
func (pp DefaultRptPathProvider) ResourceID() (*string, error) {
|
||||
rpID := requireEnv(ResourceID)
|
||||
if rpID == nil {
|
||||
instanceID, err := getInstanceIDFromMetadata()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &instanceID, nil
|
||||
}
|
||||
return rpID, nil
|
||||
}
|
||||
|
||||
func getInstanceIDFromMetadata() (instanceID string, err error) {
|
||||
client := &http.Client{}
|
||||
req, err := http.NewRequest("GET", instanceIDURL, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
req.Header.Set("Authorization", "Bearer Oracle")
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
bodyString := string(bodyBytes)
|
||||
return bodyString, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,373 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// resourcePrincipalFederationClient is the client used to to talk acquire resource principals
|
||||
// No auth client, leaf or intermediate retrievers. We use certificates retrieved by instance principals to sign the operations of
|
||||
// resource principals
|
||||
type resourcePrincipalFederationClient struct {
|
||||
tenancyID string
|
||||
instanceID string
|
||||
sessionKeySupplier sessionKeySupplier
|
||||
mux sync.Mutex
|
||||
securityToken securityToken
|
||||
path string
|
||||
|
||||
//instancePrincipalKeyProvider the instance Principal Key container
|
||||
instancePrincipalKeyProvider instancePrincipalKeyProvider
|
||||
|
||||
//ResourcePrincipalTargetServiceClient client that calls the target service to acquire a resource principal token
|
||||
ResourcePrincipalTargetServiceClient common.BaseClient
|
||||
|
||||
//ResourcePrincipalSessionTokenClient. The client used to communicate with identity to exchange a resource principal for
|
||||
// resource principal session token
|
||||
ResourcePrincipalSessionTokenClient common.BaseClient
|
||||
}
|
||||
|
||||
type resourcePrincipalTokenRequest struct {
|
||||
InstanceID string `contributesTo:"path" name:"id"`
|
||||
}
|
||||
|
||||
type resourcePrincipalTokenResponse struct {
|
||||
Body struct {
|
||||
ResourcePrincipalToken string `json:"resourcePrincipalToken"`
|
||||
ServicePrincipalSessionToken string `json:"servicePrincipalSessionToken"`
|
||||
} `presentIn:"body"`
|
||||
}
|
||||
|
||||
type resourcePrincipalSessionTokenRequestBody struct {
|
||||
ResourcePrincipalToken string `json:"resourcePrincipalToken,omitempty"`
|
||||
ServicePrincipalSessionToken string `json:"servicePrincipalSessionToken,omitempty"`
|
||||
SessionPublicKey string `json:"sessionPublicKey,omitempty"`
|
||||
}
|
||||
type resourcePrincipalSessionTokenRequest struct {
|
||||
Body resourcePrincipalSessionTokenRequestBody `contributesTo:"body"`
|
||||
}
|
||||
|
||||
//acquireResourcePrincipalToken acquires the resource principal from the target service
|
||||
func (c *resourcePrincipalFederationClient) acquireResourcePrincipalToken() (tokenResponse resourcePrincipalTokenResponse, err error) {
|
||||
rpServiceClient := c.ResourcePrincipalTargetServiceClient
|
||||
|
||||
//Set the signer of this client to be the instance principal provider
|
||||
rpServiceClient.Signer = common.DefaultRequestSigner(&c.instancePrincipalKeyProvider)
|
||||
|
||||
//Create a request with the instanceId
|
||||
request, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodGet, c.path, resourcePrincipalTokenRequest{InstanceID: c.instanceID})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//Call the target service
|
||||
response, err := rpServiceClient.Call(context.Background(), &request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer common.CloseBodyIfValid(response)
|
||||
|
||||
tokenResponse = resourcePrincipalTokenResponse{}
|
||||
err = common.UnmarshalResponse(response, &tokenResponse)
|
||||
return
|
||||
}
|
||||
|
||||
//exchangeToken exchanges a resource principal token from the target service with a session token from identity
|
||||
func (c *resourcePrincipalFederationClient) exchangeToken(publicKeyBase64 string, tokenResponse resourcePrincipalTokenResponse) (sessionToken string, err error) {
|
||||
rpServiceClient := c.ResourcePrincipalSessionTokenClient
|
||||
|
||||
//Set the signer of this client to be the instance principal provider
|
||||
rpServiceClient.Signer = common.DefaultRequestSigner(&c.instancePrincipalKeyProvider)
|
||||
|
||||
// Call identity service to get resource principal session token
|
||||
sessionTokenReq := resourcePrincipalSessionTokenRequest{
|
||||
resourcePrincipalSessionTokenRequestBody{
|
||||
ServicePrincipalSessionToken: tokenResponse.Body.ServicePrincipalSessionToken,
|
||||
ResourcePrincipalToken: tokenResponse.Body.ResourcePrincipalToken,
|
||||
SessionPublicKey: publicKeyBase64,
|
||||
},
|
||||
}
|
||||
|
||||
sessionTokenHTTPReq, err := common.MakeDefaultHTTPRequestWithTaggedStruct(http.MethodPost,
|
||||
"", sessionTokenReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sessionTokenHTTPRes, err := rpServiceClient.Call(context.Background(), &sessionTokenHTTPReq)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer common.CloseBodyIfValid(sessionTokenHTTPRes)
|
||||
|
||||
sessionTokenRes := x509FederationResponse{}
|
||||
err = common.UnmarshalResponse(sessionTokenHTTPRes, &sessionTokenRes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sessionToken = sessionTokenRes.Token.Token
|
||||
return
|
||||
}
|
||||
|
||||
//getSecurityToken makes the appropiate calls to acquire a resource principal security token
|
||||
func (c *resourcePrincipalFederationClient) getSecurityToken() (securityToken, error) {
|
||||
var err error
|
||||
ipFederationClient := c.instancePrincipalKeyProvider.FederationClient
|
||||
|
||||
common.Debugf("Refreshing instance principal token")
|
||||
//Refresh instance principal token
|
||||
if refreshable, ok := ipFederationClient.(*x509FederationClient); ok {
|
||||
err = refreshable.renewSecurityTokenIfNotValid()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
//Acquire resource principal token from target service
|
||||
common.Debugf("Acquiring resource principal token from target service")
|
||||
tokenResponse, err := c.acquireResourcePrincipalToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
//Read the public key from the session supplier.
|
||||
pem := c.sessionKeySupplier.PublicKeyPemRaw()
|
||||
pemSanitized := sanitizeCertificateString(string(pem))
|
||||
|
||||
//Exchange resource principal token for session token from identity
|
||||
common.Debugf("Exchanging resource principal token for resource principal session token")
|
||||
sessionToken, err := c.exchangeToken(pemSanitized, tokenResponse)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newPrincipalToken(sessionToken) // should be a resource principal token
|
||||
}
|
||||
|
||||
func (c *resourcePrincipalFederationClient) renewSecurityToken() (err error) {
|
||||
if err = c.sessionKeySupplier.Refresh(); err != nil {
|
||||
return fmt.Errorf("failed to refresh session key: %s", err.Error())
|
||||
}
|
||||
common.Logf("Renewing resource principal security token at: %v\n", time.Now().Format("15:04:05.000"))
|
||||
if c.securityToken, err = c.getSecurityToken(); err != nil {
|
||||
return fmt.Errorf("failed to get security token: %s", err.Error())
|
||||
}
|
||||
common.Logf("Resource principal security token renewed at: %v\n", time.Now().Format("15:04:05.000"))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//ResourcePrincipal Key provider in charge of resource principal acquiring tokens
|
||||
type resourcePrincipalKeyProviderV1 struct {
|
||||
ResourcePrincipalClient resourcePrincipalFederationClient
|
||||
}
|
||||
|
||||
func (c *resourcePrincipalFederationClient) renewSecurityTokenIfNotValid() (err error) {
|
||||
if c.securityToken == nil || !c.securityToken.Valid() {
|
||||
if err = c.renewSecurityToken(); err != nil {
|
||||
return fmt.Errorf("failed to renew resource prinicipal security token: %s", err.Error())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *resourcePrincipalFederationClient) PrivateKey() (*rsa.PrivateKey, error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err := c.renewSecurityTokenIfNotValid(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c.sessionKeySupplier.PrivateKey(), nil
|
||||
}
|
||||
|
||||
func (c *resourcePrincipalFederationClient) SecurityToken() (token string, err error) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
if err = c.renewSecurityTokenIfNotValid(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return c.securityToken.String(), nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalConfigurationProvider) PrivateRSAKey() (privateKey *rsa.PrivateKey, err error) {
|
||||
if privateKey, err = p.keyProvider.ResourcePrincipalClient.PrivateKey(); err != nil {
|
||||
err = fmt.Errorf("failed to get resource principal private key: %s", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return privateKey, nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalConfigurationProvider) KeyID() (string, error) {
|
||||
var securityToken string
|
||||
var err error
|
||||
if securityToken, err = p.keyProvider.ResourcePrincipalClient.SecurityToken(); err != nil {
|
||||
return "", fmt.Errorf("failed to get resource principal security token: %s", err.Error())
|
||||
}
|
||||
return fmt.Sprintf("ST$%s", securityToken), nil
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalConfigurationProvider) TenancyOCID() (string, error) {
|
||||
return p.keyProvider.ResourcePrincipalClient.instancePrincipalKeyProvider.TenancyOCID()
|
||||
}
|
||||
|
||||
// todo what is this
|
||||
func (p *resourcePrincipalConfigurationProvider) GetClaim(key string) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
//Resource Principals
|
||||
type resourcePrincipalConfigurationProvider struct {
|
||||
keyProvider resourcePrincipalKeyProviderV1
|
||||
region *common.Region
|
||||
}
|
||||
|
||||
func newResourcePrincipalKeyProvider(ipKeyProvider instancePrincipalKeyProvider, rpTokenTargetServiceClient, rpSessionTokenClient common.BaseClient, instanceID, path string) (keyProvider resourcePrincipalKeyProviderV1, err error) {
|
||||
rpFedClient := resourcePrincipalFederationClient{}
|
||||
rpFedClient.tenancyID = ipKeyProvider.TenancyID
|
||||
rpFedClient.instanceID = instanceID
|
||||
rpFedClient.sessionKeySupplier = newSessionKeySupplier()
|
||||
rpFedClient.ResourcePrincipalTargetServiceClient = rpTokenTargetServiceClient
|
||||
rpFedClient.ResourcePrincipalSessionTokenClient = rpSessionTokenClient
|
||||
rpFedClient.instancePrincipalKeyProvider = ipKeyProvider
|
||||
rpFedClient.path = path
|
||||
keyProvider = resourcePrincipalKeyProviderV1{ResourcePrincipalClient: rpFedClient}
|
||||
return
|
||||
}
|
||||
|
||||
func (p *resourcePrincipalConfigurationProvider) AuthType() (common.AuthConfig, error) {
|
||||
return common.AuthConfig{common.UnknownAuthenticationType, false, nil},
|
||||
fmt.Errorf("unsupported, keep the interface")
|
||||
}
|
||||
|
||||
func (p resourcePrincipalConfigurationProvider) UserOCID() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p resourcePrincipalConfigurationProvider) KeyFingerprint() (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (p resourcePrincipalConfigurationProvider) Region() (string, error) {
|
||||
if p.region == nil {
|
||||
region := p.keyProvider.ResourcePrincipalClient.instancePrincipalKeyProvider.RegionForFederationClient()
|
||||
common.Debugf("Region in resource principal configuration provider is nil. Returning instance principal federation clients region: %s", region)
|
||||
return string(region), nil
|
||||
}
|
||||
return string(*p.region), nil
|
||||
}
|
||||
|
||||
// resourcePrincipalConfigurationProviderForInstanceWithClients returns a configuration for instance principals
|
||||
// resourcePrincipalTargetServiceTokenClient and resourcePrincipalSessionTokenClient are clients that at last need to have
|
||||
// their base path and host properly set for their respective services. Additionally the clients can be further customized
|
||||
// to provide mocking or any other customization for the requests/responses
|
||||
func resourcePrincipalConfigurationProviderForInstanceWithClients(instancePrincipalProvider common.ConfigurationProvider,
|
||||
resourcePrincipalTargetServiceTokenClient, resourcePrincipalSessionTokenClient common.BaseClient, instanceID, path string) (*resourcePrincipalConfigurationProvider, error) {
|
||||
var ok bool
|
||||
var ip instancePrincipalConfigurationProvider
|
||||
if ip, ok = instancePrincipalProvider.(instancePrincipalConfigurationProvider); !ok {
|
||||
return nil, fmt.Errorf("instancePrincipalConfigurationProvider needs to be of type vald Instance Principal Configuration Provider")
|
||||
}
|
||||
|
||||
keyProvider, err := newResourcePrincipalKeyProvider(ip.keyProvider, resourcePrincipalTargetServiceTokenClient, resourcePrincipalSessionTokenClient, instanceID, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
provider := &resourcePrincipalConfigurationProvider{
|
||||
region: nil,
|
||||
keyProvider: keyProvider,
|
||||
}
|
||||
return provider, nil
|
||||
}
|
||||
|
||||
const identityResourcePrincipalSessionTokenPath = "/v1/resourcePrincipalSessionToken"
|
||||
|
||||
// resourcePrincipalConfigurationProviderForInstanceWithInterceptor creates a resource principal configuration provider with
|
||||
// a interceptor used to customize the call going to the resource principal token request to the target service
|
||||
// for a given instance ID
|
||||
func resourcePrincipalConfigurationProviderForInstanceWithInterceptor(instancePrincipalProvider common.ConfigurationProvider, resourcePrincipalTokenEndpoint, instanceID string, interceptor common.RequestInterceptor) (provider *resourcePrincipalConfigurationProvider, err error) {
|
||||
|
||||
//Build the target service client
|
||||
rpTargetServiceClient, err := common.NewClientWithConfig(instancePrincipalProvider)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rpTokenURL, err := url.Parse(resourcePrincipalTokenEndpoint)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rpTargetServiceClient.Host = rpTokenURL.Scheme + "://" + rpTokenURL.Host
|
||||
rpTargetServiceClient.Interceptor = interceptor
|
||||
|
||||
var path string
|
||||
if rpTokenURL.Path != "" {
|
||||
path = rpTokenURL.Path
|
||||
} else {
|
||||
path = identityResourcePrincipalSessionTokenPath
|
||||
}
|
||||
|
||||
//Build the identity client for token service
|
||||
rpTokenSessionClient, err := common.NewClientWithConfig(instancePrincipalProvider)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Set RPST endpoint if passed in from env var, otherwise create it from region
|
||||
resourcePrincipalSessionTokenEndpoint := requireEnv(ResourcePrincipalSessionTokenEndpoint)
|
||||
if resourcePrincipalSessionTokenEndpoint != nil {
|
||||
rpSessionTokenURL, err := url.Parse(*resourcePrincipalSessionTokenEndpoint)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rpTokenSessionClient.Host = rpSessionTokenURL.Scheme + "://" + rpSessionTokenURL.Host
|
||||
} else {
|
||||
regionStr, err := instancePrincipalProvider.Region()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("missing RPST env var and cannot determine region: %v", err)
|
||||
}
|
||||
region := common.StringToRegion(regionStr)
|
||||
rpTokenSessionClient.Host = fmt.Sprintf("https://%s", region.Endpoint("auth"))
|
||||
}
|
||||
|
||||
rpTokenSessionClient.BasePath = identityResourcePrincipalSessionTokenPath
|
||||
|
||||
return resourcePrincipalConfigurationProviderForInstanceWithClients(instancePrincipalProvider, rpTargetServiceClient, rpTokenSessionClient, instanceID, path)
|
||||
}
|
||||
|
||||
// ResourcePrincipalConfigurationProviderWithInterceptor creates a resource principal configuration provider with endpoints
|
||||
// a interceptor used to customize the call going to the resource principal token request to the target service
|
||||
// see https://godoc.org/github.com/oracle/oci-go-sdk/common#RequestInterceptor
|
||||
func ResourcePrincipalConfigurationProviderWithInterceptor(instancePrincipalProvider common.ConfigurationProvider,
|
||||
resourcePrincipalTokenEndpoint, resourcePrincipalSessionTokenEndpoint string,
|
||||
interceptor common.RequestInterceptor) (common.ConfigurationProvider, error) {
|
||||
|
||||
return resourcePrincipalConfigurationProviderForInstanceWithInterceptor(instancePrincipalProvider, resourcePrincipalTokenEndpoint, "", interceptor)
|
||||
}
|
||||
|
||||
// resourcePrincipalConfigurationProviderV1 creates a resource principal configuration provider with
|
||||
// endpoints for both resource principal token and resource principal token session
|
||||
func resourcePrincipalConfigurationProviderV1(resourcePrincipalTokenEndpoint, resourceID string) (*resourcePrincipalConfigurationProvider, error) {
|
||||
|
||||
instancePrincipalProvider, err := InstancePrincipalConfigurationProvider()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resourcePrincipalConfigurationProviderForInstanceWithInterceptor(instancePrincipalProvider, resourcePrincipalTokenEndpoint, resourceID, nil)
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha1"
|
||||
"crypto/x509"
|
||||
"fmt"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// httpGet makes a simple HTTP GET request to the given URL, expecting only "200 OK" status code.
|
||||
// This is basically for the Instance Metadata Service.
|
||||
func httpGet(dispatcher common.HTTPRequestDispatcher, url string) (body bytes.Buffer, statusCode int, err error) {
|
||||
var response *http.Response
|
||||
request, err := http.NewRequest(http.MethodGet, url, nil)
|
||||
|
||||
request.Header.Add("Authorization", "Bearer Oracle")
|
||||
|
||||
if response, err = dispatcher.Do(request); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
statusCode = response.StatusCode
|
||||
common.IfDebug(func() {
|
||||
if dump, e := httputil.DumpResponse(response, true); e == nil {
|
||||
common.Logf("Dump Response %v", string(dump))
|
||||
} else {
|
||||
common.Debugln(e)
|
||||
}
|
||||
})
|
||||
|
||||
defer response.Body.Close()
|
||||
if _, err = body.ReadFrom(response.Body); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if statusCode != http.StatusOK {
|
||||
err = fmt.Errorf("HTTP Get failed: URL: %s, Status: %s, Message: %s",
|
||||
url, response.Status, body.String())
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func extractTenancyIDFromCertificate(cert *x509.Certificate) string {
|
||||
for _, nameAttr := range cert.Subject.Names {
|
||||
value := nameAttr.Value.(string)
|
||||
if strings.HasPrefix(value, "opc-tenant:") {
|
||||
return value[len("opc-tenant:"):]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func fingerprint(certificate *x509.Certificate) string {
|
||||
fingerprint := sha1.Sum(certificate.Raw)
|
||||
return colonSeparatedString(fingerprint)
|
||||
}
|
||||
|
||||
func colonSeparatedString(fingerprint [sha1.Size]byte) string {
|
||||
spaceSeparated := fmt.Sprintf("% x", fingerprint)
|
||||
return strings.Replace(spaceSeparated, " ", ":", -1)
|
||||
}
|
||||
|
||||
func sanitizeCertificateString(certString string) string {
|
||||
certString = strings.Replace(certString, "-----BEGIN CERTIFICATE-----", "", -1)
|
||||
certString = strings.Replace(certString, "-----END CERTIFICATE-----", "", -1)
|
||||
certString = strings.Replace(certString, "-----BEGIN PUBLIC KEY-----", "", -1)
|
||||
certString = strings.Replace(certString, "-----END PUBLIC KEY-----", "", -1)
|
||||
certString = strings.Replace(certString, "\n", "", -1)
|
||||
return certString
|
||||
}
|
||||
|
||||
// GetGenericConfigurationProvider checks auth config paras in config file and return the final configuration provider
|
||||
func GetGenericConfigurationProvider(configProvider common.ConfigurationProvider) (common.ConfigurationProvider, error) {
|
||||
if authConfig, err := configProvider.AuthType(); err == nil && authConfig.IsFromConfigFile {
|
||||
switch authConfig.AuthType {
|
||||
case common.InstancePrincipalDelegationToken:
|
||||
return InstancePrincipalDelegationTokenConfigurationProvider(authConfig.OboToken)
|
||||
case common.InstancePrincipal:
|
||||
return InstancePrincipalConfigurationProvider()
|
||||
case common.UserPrincipal:
|
||||
return configProvider, nil
|
||||
}
|
||||
}
|
||||
return configProvider, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,584 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
// Package common provides supporting functions and structs used by service packages
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"os"
|
||||
"os/user"
|
||||
"path"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// DefaultHostURLTemplate The default url template for service hosts
|
||||
DefaultHostURLTemplate = "%s.%s.oraclecloud.com"
|
||||
|
||||
// requestHeaderAccept The key for passing a header to indicate Accept
|
||||
requestHeaderAccept = "Accept"
|
||||
|
||||
// requestHeaderAuthorization The key for passing a header to indicate Authorization
|
||||
requestHeaderAuthorization = "Authorization"
|
||||
|
||||
// requestHeaderContentLength The key for passing a header to indicate Content Length
|
||||
requestHeaderContentLength = "Content-Length"
|
||||
|
||||
// requestHeaderContentType The key for passing a header to indicate Content Type
|
||||
requestHeaderContentType = "Content-Type"
|
||||
|
||||
// requestHeaderExpect The key for passing a header to indicate Expect/100-Continue
|
||||
requestHeaderExpect = "Expect"
|
||||
|
||||
// requestHeaderDate The key for passing a header to indicate Date
|
||||
requestHeaderDate = "Date"
|
||||
|
||||
// requestHeaderIfMatch The key for passing a header to indicate If Match
|
||||
requestHeaderIfMatch = "if-match"
|
||||
|
||||
// requestHeaderOpcClientInfo The key for passing a header to indicate OPC Client Info
|
||||
requestHeaderOpcClientInfo = "opc-client-info"
|
||||
|
||||
// requestHeaderOpcRetryToken The key for passing a header to indicate OPC Retry Token
|
||||
requestHeaderOpcRetryToken = "opc-retry-token"
|
||||
|
||||
// requestHeaderOpcRequestID The key for unique Oracle-assigned identifier for the request.
|
||||
requestHeaderOpcRequestID = "opc-request-id"
|
||||
|
||||
// requestHeaderOpcClientRequestID The key for unique Oracle-assigned identifier for the request.
|
||||
requestHeaderOpcClientRequestID = "opc-client-request-id"
|
||||
|
||||
// requestHeaderUserAgent The key for passing a header to indicate User Agent
|
||||
requestHeaderUserAgent = "User-Agent"
|
||||
|
||||
// requestHeaderXContentSHA256 The key for passing a header to indicate SHA256 hash
|
||||
requestHeaderXContentSHA256 = "X-Content-SHA256"
|
||||
|
||||
// requestHeaderOpcOboToken The key for passing a header to use obo token
|
||||
requestHeaderOpcOboToken = "opc-obo-token"
|
||||
|
||||
// private constants
|
||||
defaultScheme = "https"
|
||||
defaultSDKMarker = "Oracle-GoSDK"
|
||||
defaultUserAgentTemplate = "%s/%s (%s/%s; go/%s)" //SDK/SDKVersion (OS/OSVersion; Lang/LangVersion)
|
||||
// http.Client.Timeout includes Dial, TLSHandshake, Request, Response header and body
|
||||
defaultTimeout = 60 * time.Second
|
||||
defaultConfigFileName = "config"
|
||||
defaultConfigDirName = ".oci"
|
||||
configFilePathEnvVarName = "OCI_CONFIG_FILE"
|
||||
|
||||
secondaryConfigDirName = ".oraclebmc"
|
||||
maxBodyLenForDebug = 1024 * 1000
|
||||
)
|
||||
|
||||
// RequestInterceptor function used to customize the request before calling the underlying service
|
||||
type RequestInterceptor func(*http.Request) error
|
||||
|
||||
// HTTPRequestDispatcher wraps the execution of a http request, it is generally implemented by
|
||||
// http.Client.Do, but can be customized for testing
|
||||
type HTTPRequestDispatcher interface {
|
||||
Do(req *http.Request) (*http.Response, error)
|
||||
}
|
||||
|
||||
// CustomClientConfiguration contains configurations set at client level, currently it only includes RetryPolicy
|
||||
type CustomClientConfiguration struct {
|
||||
RetryPolicy *RetryPolicy
|
||||
}
|
||||
|
||||
// BaseClient struct implements all basic operations to call oci web services.
|
||||
type BaseClient struct {
|
||||
//HTTPClient performs the http network operations
|
||||
HTTPClient HTTPRequestDispatcher
|
||||
|
||||
//Signer performs auth operation
|
||||
Signer HTTPRequestSigner
|
||||
|
||||
//A request interceptor can be used to customize the request before signing and dispatching
|
||||
Interceptor RequestInterceptor
|
||||
|
||||
//The host of the service
|
||||
Host string
|
||||
|
||||
//The user agent
|
||||
UserAgent string
|
||||
|
||||
//Base path for all operations of this client
|
||||
BasePath string
|
||||
|
||||
Configuration CustomClientConfiguration
|
||||
}
|
||||
|
||||
// SetCustomClientConfiguration sets client with retry and other custom configurations
|
||||
func (client *BaseClient) SetCustomClientConfiguration(config CustomClientConfiguration) {
|
||||
client.Configuration = config
|
||||
}
|
||||
|
||||
// RetryPolicy returns the retryPolicy configured for client
|
||||
func (client *BaseClient) RetryPolicy() *RetryPolicy {
|
||||
return client.Configuration.RetryPolicy
|
||||
}
|
||||
|
||||
// Endpoint returns the endpoint configured for client
|
||||
func (client *BaseClient) Endpoint() string {
|
||||
host := client.Host
|
||||
if !strings.Contains(host, "http") &&
|
||||
!strings.Contains(host, "https") {
|
||||
host = fmt.Sprintf("%s://%s", defaultScheme, host)
|
||||
}
|
||||
return host
|
||||
}
|
||||
|
||||
func defaultUserAgent() string {
|
||||
userAgent := fmt.Sprintf(defaultUserAgentTemplate, defaultSDKMarker, Version(), runtime.GOOS, runtime.GOARCH, runtime.Version())
|
||||
appendUA := os.Getenv("OCI_SDK_APPEND_USER_AGENT")
|
||||
if appendUA != "" {
|
||||
userAgent = fmt.Sprintf("%s %s", userAgent, appendUA)
|
||||
}
|
||||
return userAgent
|
||||
}
|
||||
|
||||
var clientCounter int64
|
||||
|
||||
func getNextSeed() int64 {
|
||||
newCounterValue := atomic.AddInt64(&clientCounter, 1)
|
||||
return newCounterValue + time.Now().UnixNano()
|
||||
}
|
||||
|
||||
func newBaseClient(signer HTTPRequestSigner, dispatcher HTTPRequestDispatcher) BaseClient {
|
||||
rand.Seed(getNextSeed())
|
||||
return BaseClient{
|
||||
UserAgent: defaultUserAgent(),
|
||||
Interceptor: nil,
|
||||
Signer: signer,
|
||||
HTTPClient: dispatcher,
|
||||
}
|
||||
}
|
||||
|
||||
func defaultHTTPDispatcher() http.Client {
|
||||
var httpClient http.Client
|
||||
|
||||
if isExpectHeaderEnabled := getExpectHeaderConfig(); isExpectHeaderEnabled {
|
||||
var tp http.RoundTripper = &http.Transport{
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 3 * time.Second,
|
||||
}
|
||||
httpClient = http.Client{
|
||||
Transport: tp,
|
||||
Timeout: defaultTimeout,
|
||||
}
|
||||
} else {
|
||||
httpClient = http.Client{
|
||||
Timeout: defaultTimeout,
|
||||
}
|
||||
}
|
||||
return httpClient
|
||||
}
|
||||
|
||||
func defaultBaseClient(provider KeyProvider) BaseClient {
|
||||
dispatcher := defaultHTTPDispatcher()
|
||||
signer := DefaultRequestSigner(provider)
|
||||
return newBaseClient(signer, &dispatcher)
|
||||
}
|
||||
|
||||
//DefaultBaseClientWithSigner creates a default base client with a given signer
|
||||
func DefaultBaseClientWithSigner(signer HTTPRequestSigner) BaseClient {
|
||||
dispatcher := defaultHTTPDispatcher()
|
||||
return newBaseClient(signer, &dispatcher)
|
||||
}
|
||||
|
||||
// NewClientWithConfig Create a new client with a configuration provider, the configuration provider
|
||||
// will be used for the default signer as well as reading the region
|
||||
// This function does not check for valid regions to implement forward compatibility
|
||||
func NewClientWithConfig(configProvider ConfigurationProvider) (client BaseClient, err error) {
|
||||
var ok bool
|
||||
if ok, err = IsConfigurationProviderValid(configProvider); !ok {
|
||||
err = fmt.Errorf("can not create client, bad configuration: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
client = defaultBaseClient(configProvider)
|
||||
|
||||
if authConfig, e := configProvider.AuthType(); e == nil && authConfig.OboToken != nil {
|
||||
Debugf("authConfig's authType is %s, and token content is %s", authConfig.AuthType, *authConfig.OboToken)
|
||||
signOboToken(&client, *authConfig.OboToken, configProvider)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// NewClientWithOboToken Create a new client that will use oboToken for auth
|
||||
func NewClientWithOboToken(configProvider ConfigurationProvider, oboToken string) (client BaseClient, err error) {
|
||||
client, err = NewClientWithConfig(configProvider)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
signOboToken(&client, oboToken, configProvider)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Add obo token header to Interceptor and sign to client
|
||||
func signOboToken(client *BaseClient, oboToken string, configProvider ConfigurationProvider) {
|
||||
// Interceptor to add obo token header
|
||||
client.Interceptor = func(request *http.Request) error {
|
||||
request.Header.Add(requestHeaderOpcOboToken, oboToken)
|
||||
return nil
|
||||
}
|
||||
// Obo token will also be signed
|
||||
defaultHeaders := append(DefaultGenericHeaders(), requestHeaderOpcOboToken)
|
||||
client.Signer = RequestSigner(configProvider, defaultHeaders, DefaultBodyHeaders())
|
||||
}
|
||||
|
||||
func getHomeFolder() string {
|
||||
current, e := user.Current()
|
||||
if e != nil {
|
||||
//Give up and try to return something sensible
|
||||
home := os.Getenv("HOME")
|
||||
if home == "" {
|
||||
home = os.Getenv("USERPROFILE")
|
||||
}
|
||||
return home
|
||||
}
|
||||
return current.HomeDir
|
||||
}
|
||||
|
||||
// DefaultConfigProvider returns the default config provider. The default config provider
|
||||
// will look for configurations in 3 places: file in $HOME/.oci/config, HOME/.obmcs/config and
|
||||
// variables names starting with the string TF_VAR. If the same configuration is found in multiple
|
||||
// places the provider will prefer the first one.
|
||||
// If the config file is not placed in the default location, the environment variable
|
||||
// OCI_CONFIG_FILE can provide the config file location.
|
||||
func DefaultConfigProvider() ConfigurationProvider {
|
||||
defaultConfigFile := getDefaultConfigFilePath()
|
||||
homeFolder := getHomeFolder()
|
||||
secondaryConfigFile := path.Join(homeFolder, secondaryConfigDirName, defaultConfigFileName)
|
||||
|
||||
defaultFileProvider, _ := ConfigurationProviderFromFile(defaultConfigFile, "")
|
||||
secondaryFileProvider, _ := ConfigurationProviderFromFile(secondaryConfigFile, "")
|
||||
environmentProvider := environmentConfigurationProvider{EnvironmentVariablePrefix: "TF_VAR"}
|
||||
|
||||
provider, _ := ComposingConfigurationProvider([]ConfigurationProvider{defaultFileProvider, secondaryFileProvider, environmentProvider})
|
||||
Debugf("Configuration provided by: %s", provider)
|
||||
return provider
|
||||
}
|
||||
|
||||
func getDefaultConfigFilePath() string {
|
||||
homeFolder := getHomeFolder()
|
||||
defaultConfigFile := path.Join(homeFolder, defaultConfigDirName, defaultConfigFileName)
|
||||
if _, err := os.Stat(defaultConfigFile); err == nil {
|
||||
return defaultConfigFile
|
||||
}
|
||||
Debugf("The %s does not exist, will check env var %s for file path.", defaultConfigFile, configFilePathEnvVarName)
|
||||
// Read configuration file path from OCI_CONFIG_FILE env var
|
||||
fallbackConfigFile, existed := os.LookupEnv(configFilePathEnvVarName)
|
||||
if !existed {
|
||||
Debugf("The env var %s does not exist...", configFilePathEnvVarName)
|
||||
return defaultConfigFile
|
||||
}
|
||||
if _, err := os.Stat(fallbackConfigFile); os.IsNotExist(err) {
|
||||
Debugf("The specified cfg file path in the env var %s does not exist: %s", configFilePathEnvVarName, fallbackConfigFile)
|
||||
return defaultConfigFile
|
||||
}
|
||||
return fallbackConfigFile
|
||||
}
|
||||
|
||||
// CustomProfileConfigProvider returns the config provider of given profile. The custom profile config provider
|
||||
// will look for configurations in 2 places: file in $HOME/.oci/config, and variables names starting with the
|
||||
// string TF_VAR. If the same configuration is found in multiple places the provider will prefer the first one.
|
||||
func CustomProfileConfigProvider(customConfigPath string, profile string) ConfigurationProvider {
|
||||
homeFolder := getHomeFolder()
|
||||
if customConfigPath == "" {
|
||||
customConfigPath = path.Join(homeFolder, defaultConfigDirName, defaultConfigFileName)
|
||||
}
|
||||
customFileProvider, _ := ConfigurationProviderFromFileWithProfile(customConfigPath, profile, "")
|
||||
defaultFileProvider, _ := ConfigurationProviderFromFileWithProfile(customConfigPath, "DEFAULT", "")
|
||||
environmentProvider := environmentConfigurationProvider{EnvironmentVariablePrefix: "TF_VAR"}
|
||||
provider, _ := ComposingConfigurationProvider([]ConfigurationProvider{customFileProvider, defaultFileProvider, environmentProvider})
|
||||
Debugf("Configuration provided by: %s", provider)
|
||||
return provider
|
||||
}
|
||||
|
||||
func (client *BaseClient) prepareRequest(request *http.Request) (err error) {
|
||||
if client.UserAgent == "" {
|
||||
return fmt.Errorf("user agent can not be blank")
|
||||
}
|
||||
|
||||
if request.Header == nil {
|
||||
request.Header = http.Header{}
|
||||
}
|
||||
request.Header.Set(requestHeaderUserAgent, client.UserAgent)
|
||||
request.Header.Set(requestHeaderDate, time.Now().UTC().Format(http.TimeFormat))
|
||||
|
||||
if !strings.Contains(client.Host, "http") &&
|
||||
!strings.Contains(client.Host, "https") {
|
||||
client.Host = fmt.Sprintf("%s://%s", defaultScheme, client.Host)
|
||||
}
|
||||
|
||||
clientURL, err := url.Parse(client.Host)
|
||||
if err != nil {
|
||||
return fmt.Errorf("host is invalid. %s", err.Error())
|
||||
}
|
||||
request.URL.Host = clientURL.Host
|
||||
request.URL.Scheme = clientURL.Scheme
|
||||
currentPath := request.URL.Path
|
||||
if !strings.Contains(currentPath, fmt.Sprintf("/%s", client.BasePath)) {
|
||||
request.URL.Path = path.Clean(fmt.Sprintf("/%s/%s", client.BasePath, currentPath))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (client BaseClient) intercept(request *http.Request) (err error) {
|
||||
if client.Interceptor != nil {
|
||||
err = client.Interceptor(request)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// checkForSuccessfulResponse checks if the response is successful
|
||||
// If Error Code is 4XX/5XX and debug level is set to info, will log the request and response
|
||||
func checkForSuccessfulResponse(res *http.Response, requestBody *io.ReadCloser) error {
|
||||
familyStatusCode := res.StatusCode / 100
|
||||
if familyStatusCode == 4 || familyStatusCode == 5 {
|
||||
IfInfo(func() {
|
||||
// If debug level is set to verbose, the request and request body will be dumped and logged under debug level, this is to avoid duplicate logging
|
||||
if defaultLogger.LogLevel() < verboseLogging {
|
||||
logRequest(res.Request, Logf, noLogging)
|
||||
if requestBody != nil && *requestBody != http.NoBody {
|
||||
bodyContent, _ := ioutil.ReadAll(*requestBody)
|
||||
Logf("Dump Request Body: \n%s", string(bodyContent))
|
||||
}
|
||||
}
|
||||
logResponse(res, Logf, infoLogging)
|
||||
})
|
||||
return newServiceFailureFromResponse(res)
|
||||
}
|
||||
IfDebug(func() {
|
||||
logResponse(res, Debugf, verboseLogging)
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func logRequest(request *http.Request, fn func(format string, v ...interface{}), bodyLoggingLevel int) {
|
||||
if request == nil {
|
||||
return
|
||||
}
|
||||
dumpBody := true
|
||||
if checkBodyLengthExceedLimit(request.ContentLength) {
|
||||
fn("not dumping body too big\n")
|
||||
dumpBody = false
|
||||
}
|
||||
|
||||
dumpBody = dumpBody && defaultLogger.LogLevel() >= bodyLoggingLevel && bodyLoggingLevel != noLogging
|
||||
if dump, e := httputil.DumpRequestOut(request, dumpBody); e == nil {
|
||||
fn("Dump Request %s", string(dump))
|
||||
} else {
|
||||
fn("%v\n", e)
|
||||
}
|
||||
}
|
||||
|
||||
func logResponse(response *http.Response, fn func(format string, v ...interface{}), bodyLoggingLevel int) {
|
||||
if response == nil {
|
||||
return
|
||||
}
|
||||
dumpBody := true
|
||||
if checkBodyLengthExceedLimit(response.ContentLength) {
|
||||
fn("not dumping body too big\n")
|
||||
dumpBody = false
|
||||
}
|
||||
dumpBody = dumpBody && defaultLogger.LogLevel() >= bodyLoggingLevel && bodyLoggingLevel != noLogging
|
||||
if dump, e := httputil.DumpResponse(response, dumpBody); e == nil {
|
||||
fn("Dump Response %s", string(dump))
|
||||
} else {
|
||||
fn("%v\n", e)
|
||||
}
|
||||
}
|
||||
|
||||
func checkBodyLengthExceedLimit(contentLength int64) bool {
|
||||
if contentLength > maxBodyLenForDebug {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// OCIRequest is any request made to an OCI service.
|
||||
type OCIRequest interface {
|
||||
// HTTPRequest assembles an HTTP request.
|
||||
HTTPRequest(method, path string, binaryRequestBody *OCIReadSeekCloser) (http.Request, error)
|
||||
}
|
||||
|
||||
// RequestMetadata is metadata about an OCIRequest. This structure represents the behavior exhibited by the SDK when
|
||||
// issuing (or reissuing) a request.
|
||||
type RequestMetadata struct {
|
||||
// RetryPolicy is the policy for reissuing the request. If no retry policy is set on the request,
|
||||
// then the request will be issued exactly once.
|
||||
RetryPolicy *RetryPolicy
|
||||
}
|
||||
|
||||
// OCIReadSeekCloser is a thread-safe io.ReadSeekCloser to prevent racing with retrying binary requests
|
||||
type OCIReadSeekCloser struct {
|
||||
rc io.ReadCloser
|
||||
lock sync.Mutex
|
||||
isClosed bool
|
||||
}
|
||||
|
||||
// NewOCIReadSeekCloser constructs OCIReadSeekCloser, the only input is binary request body
|
||||
func NewOCIReadSeekCloser(rc io.ReadCloser) *OCIReadSeekCloser {
|
||||
rsc := OCIReadSeekCloser{}
|
||||
rsc.rc = rc
|
||||
return &rsc
|
||||
}
|
||||
|
||||
// Seek is a thread-safe operation, it implements io.seek() interface, if the original request body implements io.seek()
|
||||
// interface, or implements "well-known" data type like os.File, io.SectionReader, or wrapped by ioutil.NopCloser can be supported
|
||||
func (rsc *OCIReadSeekCloser) Seek(offset int64, whence int) (int64, error) {
|
||||
rsc.lock.Lock()
|
||||
defer rsc.lock.Unlock()
|
||||
|
||||
if _, ok := rsc.rc.(io.Seeker); ok {
|
||||
return rsc.rc.(io.Seeker).Seek(offset, whence)
|
||||
}
|
||||
// once the binary request body is wrapped with ioutil.NopCloser:
|
||||
if reflect.TypeOf(rsc.rc) == reflect.TypeOf(ioutil.NopCloser(nil)) {
|
||||
unwrappedInterface := reflect.ValueOf(rsc.rc).Field(0).Interface()
|
||||
if _, ok := unwrappedInterface.(io.Seeker); ok {
|
||||
return unwrappedInterface.(io.Seeker).Seek(offset, whence)
|
||||
}
|
||||
}
|
||||
return 0, fmt.Errorf("current binary request body type is not seekable, if want to use retry feature, please make sure the request body implements seek() method")
|
||||
}
|
||||
|
||||
// Close is a thread-safe operation, it closes the instance of the OCIReadSeekCloser's access to the underlying io.ReadCloser.
|
||||
func (rsc *OCIReadSeekCloser) Close() error {
|
||||
rsc.lock.Lock()
|
||||
defer rsc.lock.Unlock()
|
||||
rsc.isClosed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read is a thread-safe operation, it implements io.Read() interface
|
||||
func (rsc *OCIReadSeekCloser) Read(p []byte) (n int, err error) {
|
||||
rsc.lock.Lock()
|
||||
defer rsc.lock.Unlock()
|
||||
|
||||
if rsc.isClosed {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
return rsc.rc.Read(p)
|
||||
}
|
||||
|
||||
// Seekable is used for check if the binary request body can be seek or no
|
||||
func (rsc *OCIReadSeekCloser) Seekable() bool {
|
||||
if rsc == nil {
|
||||
return false
|
||||
}
|
||||
if _, ok := rsc.rc.(io.Seeker); ok {
|
||||
return true
|
||||
}
|
||||
// once the binary request body is wrapped with ioutil.NopCloser:
|
||||
if reflect.TypeOf(rsc.rc) == reflect.TypeOf(ioutil.NopCloser(nil)) {
|
||||
if _, ok := reflect.ValueOf(rsc.rc).Field(0).Interface().(io.Seeker); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// OCIResponse is the response from issuing a request to an OCI service.
|
||||
type OCIResponse interface {
|
||||
// HTTPResponse returns the raw HTTP response.
|
||||
HTTPResponse() *http.Response
|
||||
}
|
||||
|
||||
// OCIOperation is the generalization of a request-response cycle undergone by an OCI service.
|
||||
type OCIOperation func(context.Context, OCIRequest, *OCIReadSeekCloser) (OCIResponse, error)
|
||||
|
||||
//ClientCallDetails a set of settings used by the a single Call operation of the http Client
|
||||
type ClientCallDetails struct {
|
||||
Signer HTTPRequestSigner
|
||||
}
|
||||
|
||||
// Call executes the http request with the given context
|
||||
func (client BaseClient) Call(ctx context.Context, request *http.Request) (response *http.Response, err error) {
|
||||
return client.CallWithDetails(ctx, request, ClientCallDetails{Signer: client.Signer})
|
||||
}
|
||||
|
||||
// CallWithDetails executes the http request, the given context using details specified in the parameters, this function
|
||||
// provides a way to override some settings present in the client
|
||||
func (client BaseClient) CallWithDetails(ctx context.Context, request *http.Request, details ClientCallDetails) (response *http.Response, err error) {
|
||||
Debugln("Attempting to call downstream service")
|
||||
request = request.WithContext(ctx)
|
||||
|
||||
err = client.prepareRequest(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//Intercept
|
||||
err = client.intercept(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//Sign the request
|
||||
err = details.Signer.Sign(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
//Copy request body and save for logging
|
||||
dumpRequestBody := ioutil.NopCloser(bytes.NewBuffer(nil))
|
||||
if request.Body != nil && !checkBodyLengthExceedLimit(request.ContentLength) {
|
||||
if dumpRequestBody, request.Body, err = drainBody(request.Body); err != nil {
|
||||
dumpRequestBody = ioutil.NopCloser(bytes.NewBuffer(nil))
|
||||
}
|
||||
}
|
||||
IfDebug(func() {
|
||||
logRequest(request, Debugf, verboseLogging)
|
||||
})
|
||||
|
||||
//Execute the http request
|
||||
response, err = client.HTTPClient.Do(request)
|
||||
|
||||
if err != nil {
|
||||
IfInfo(func() {
|
||||
Logf("%v\n", err)
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err = checkForSuccessfulResponse(response, &dumpRequestBody)
|
||||
return
|
||||
}
|
||||
|
||||
//CloseBodyIfValid closes the body of an http response if the response and the body are valid
|
||||
func CloseBodyIfValid(httpResponse *http.Response) {
|
||||
if httpResponse != nil && httpResponse.Body != nil {
|
||||
httpResponse.Body.Close()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,479 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
//Region type for regions
|
||||
type Region string
|
||||
|
||||
const (
|
||||
instanceMetadataRegionInfoURLV2 = "http://169.254.169.254/opc/v2/instance/regionInfo"
|
||||
|
||||
//RegionSEA region SEA
|
||||
RegionSEA Region = "sea"
|
||||
//RegionCAToronto1 region for Toronto
|
||||
RegionCAToronto1 Region = "ca-toronto-1"
|
||||
//RegionCAMontreal1 region for Montreal
|
||||
RegionCAMontreal1 Region = "ca-montreal-1"
|
||||
//RegionPHX region PHX
|
||||
RegionPHX Region = "us-phoenix-1"
|
||||
//RegionIAD region IAD
|
||||
RegionIAD Region = "us-ashburn-1"
|
||||
//RegionSJC1 region SJC
|
||||
RegionSJC1 Region = "us-sanjose-1"
|
||||
|
||||
//RegionFRA region FRA
|
||||
RegionFRA Region = "eu-frankfurt-1"
|
||||
|
||||
//RegionUKCardiff1 region for Cardiff
|
||||
RegionUKCardiff1 Region = "uk-cardiff-1"
|
||||
//RegionLHR region LHR
|
||||
RegionLHR Region = "uk-london-1"
|
||||
|
||||
//RegionAPTokyo1 region for Tokyo
|
||||
RegionAPTokyo1 Region = "ap-tokyo-1"
|
||||
//RegionAPOsaka1 region for Osaka
|
||||
RegionAPOsaka1 Region = "ap-osaka-1"
|
||||
//RegionAPChiyoda1 region for Chiyoda
|
||||
RegionAPChiyoda1 Region = "ap-chiyoda-1"
|
||||
//RegionAPSeoul1 region for Seoul
|
||||
RegionAPSeoul1 Region = "ap-seoul-1"
|
||||
//RegionAPChuncheon1 region for Chuncheon
|
||||
RegionAPChuncheon1 Region = "ap-chuncheon-1"
|
||||
//RegionAPMumbai1 region for Mumbai
|
||||
RegionAPMumbai1 Region = "ap-mumbai-1"
|
||||
//RegionAPHyderabad1 region for Hyderabad
|
||||
RegionAPHyderabad1 Region = "ap-hyderabad-1"
|
||||
//RegionAPMelbourne1 region for Melbourne
|
||||
RegionAPMelbourne1 Region = "ap-melbourne-1"
|
||||
//RegionAPSydney1 region for Sydney
|
||||
RegionAPSydney1 Region = "ap-sydney-1"
|
||||
|
||||
//RegionMEJeddah1 region for Jeddah
|
||||
RegionMEJeddah1 Region = "me-jeddah-1"
|
||||
//RegionMEDubai1 region for Dubai
|
||||
RegionMEDubai1 Region = "me-dubai-1"
|
||||
|
||||
//RegionEUZurich1 region for Zurich
|
||||
RegionEUZurich1 Region = "eu-zurich-1"
|
||||
//RegionEUAmsterdam1 region for Amsterdam
|
||||
RegionEUAmsterdam1 Region = "eu-amsterdam-1"
|
||||
|
||||
//RegionSASaopaulo1 region for Sao Paulo
|
||||
RegionSASaopaulo1 Region = "sa-saopaulo-1"
|
||||
//RegionSASantiago1 region for santiago
|
||||
RegionSASantiago1 Region = "sa-santiago-1"
|
||||
//RegionSAVinhedo1 region for vinhedo
|
||||
RegionSAVinhedo1 Region = "sa-vinhedo-1"
|
||||
|
||||
//RegionUSLangley1 region for Langley
|
||||
RegionUSLangley1 Region = "us-langley-1"
|
||||
//RegionUSLuke1 region for Luke
|
||||
RegionUSLuke1 Region = "us-luke-1"
|
||||
|
||||
//RegionUSGovAshburn1 gov region Ashburn
|
||||
RegionUSGovAshburn1 Region = "us-gov-ashburn-1"
|
||||
//RegionUSGovChicago1 gov region Chicago
|
||||
RegionUSGovChicago1 Region = "us-gov-chicago-1"
|
||||
//RegionUSGovPhoenix1 region for Phoenix
|
||||
RegionUSGovPhoenix1 Region = "us-gov-phoenix-1"
|
||||
//RegionUKGovLondon1 gov region London
|
||||
RegionUKGovLondon1 Region = "uk-gov-london-1"
|
||||
//RegionUKGovCardiff1 gov region Cardiff
|
||||
RegionUKGovCardiff1 Region = "uk-gov-cardiff-1"
|
||||
|
||||
// Region Metadata Configuration File
|
||||
regionMetadataCfgDirName = ".oci"
|
||||
regionMetadataCfgFileName = "regions-config.json"
|
||||
|
||||
// Region Metadata Environment Variable
|
||||
regionMetadataEnvVarName = "OCI_REGION_METADATA"
|
||||
|
||||
// Region Metadata
|
||||
regionIdentifierPropertyName = "regionIdentifier" // e.g. "ap-sydney-1"
|
||||
realmKeyPropertyName = "realmKey" // e.g. "oc1"
|
||||
realmDomainComponentPropertyName = "realmDomainComponent" // e.g. "oraclecloud.com"
|
||||
regionKeyPropertyName = "regionKey" // e.g. "SYD"
|
||||
)
|
||||
|
||||
var shortNameRegion = map[string]Region{
|
||||
"sea": RegionSEA,
|
||||
"phx": RegionPHX,
|
||||
"iad": RegionIAD,
|
||||
"fra": RegionFRA,
|
||||
"lhr": RegionLHR,
|
||||
"cwl": RegionUKCardiff1,
|
||||
"ams": RegionEUAmsterdam1,
|
||||
"zrh": RegionEUZurich1,
|
||||
"mel": RegionAPMelbourne1,
|
||||
"bom": RegionAPMumbai1,
|
||||
"hyd": RegionAPHyderabad1,
|
||||
"icn": RegionAPSeoul1,
|
||||
"yny": RegionAPChuncheon1,
|
||||
"nrt": RegionAPTokyo1,
|
||||
"kix": RegionAPOsaka1,
|
||||
"nja": RegionAPChiyoda1,
|
||||
"jed": RegionMEJeddah1,
|
||||
"dxb": RegionMEDubai1,
|
||||
"syd": RegionAPSydney1,
|
||||
"yul": RegionCAMontreal1,
|
||||
"yyz": RegionCAToronto1,
|
||||
"sjc": RegionSJC1,
|
||||
"gru": RegionSASaopaulo1,
|
||||
"scl": RegionSASantiago1,
|
||||
"vcp": RegionSAVinhedo1,
|
||||
"ltn": RegionUKGovLondon1,
|
||||
"brs": RegionUKGovCardiff1,
|
||||
}
|
||||
|
||||
var realm = map[string]string{
|
||||
"oc1": "oraclecloud.com",
|
||||
"oc2": "oraclegovcloud.com",
|
||||
"oc3": "oraclegovcloud.com",
|
||||
"oc4": "oraclegovcloud.uk",
|
||||
"oc8": "oraclecloud8.com",
|
||||
}
|
||||
|
||||
var regionRealm = map[Region]string{
|
||||
RegionPHX: "oc1",
|
||||
RegionIAD: "oc1",
|
||||
RegionFRA: "oc1",
|
||||
RegionLHR: "oc1",
|
||||
RegionSJC1: "oc1",
|
||||
|
||||
RegionUKCardiff1: "oc1",
|
||||
|
||||
RegionCAToronto1: "oc1",
|
||||
RegionCAMontreal1: "oc1",
|
||||
|
||||
RegionAPTokyo1: "oc1",
|
||||
RegionAPOsaka1: "oc1",
|
||||
RegionAPSeoul1: "oc1",
|
||||
RegionAPChuncheon1: "oc1",
|
||||
RegionAPSydney1: "oc1",
|
||||
RegionAPMumbai1: "oc1",
|
||||
RegionAPHyderabad1: "oc1",
|
||||
RegionAPMelbourne1: "oc1",
|
||||
|
||||
RegionMEJeddah1: "oc1",
|
||||
RegionMEDubai1: "oc1",
|
||||
|
||||
RegionEUZurich1: "oc1",
|
||||
RegionEUAmsterdam1: "oc1",
|
||||
|
||||
RegionSASaopaulo1: "oc1",
|
||||
RegionSASantiago1: "oc1",
|
||||
RegionSAVinhedo1: "oc1",
|
||||
|
||||
RegionUSLangley1: "oc2",
|
||||
RegionUSLuke1: "oc2",
|
||||
|
||||
RegionUSGovAshburn1: "oc3",
|
||||
RegionUSGovChicago1: "oc3",
|
||||
RegionUSGovPhoenix1: "oc3",
|
||||
RegionUKGovCardiff1: "oc4",
|
||||
RegionUKGovLondon1: "oc4",
|
||||
|
||||
RegionAPChiyoda1: "oc8",
|
||||
}
|
||||
|
||||
// External region metadata info flag, used to control adding these metadata region info only once.
|
||||
var readCfgFile, readEnvVar, visitIMDS bool = true, true, false
|
||||
|
||||
// getRegionInfoFromInstanceMetadataService gets the region information
|
||||
var getRegionInfoFromInstanceMetadataService = getRegionInfoFromInstanceMetadataServiceProd
|
||||
|
||||
// Endpoint returns a endpoint for a service
|
||||
func (region Region) Endpoint(service string) string {
|
||||
return fmt.Sprintf("%s.%s.%s", service, region, region.secondLevelDomain())
|
||||
}
|
||||
|
||||
// EndpointForTemplate returns a endpoint for a service based on template, only unknown region name can fall back to "oc1", but not short code region name.
|
||||
func (region Region) EndpointForTemplate(service string, serviceEndpointTemplate string) string {
|
||||
if serviceEndpointTemplate == "" {
|
||||
return region.Endpoint(service)
|
||||
}
|
||||
|
||||
// replace service prefix
|
||||
endpoint := strings.Replace(serviceEndpointTemplate, "{serviceEndpointPrefix}", service, 1)
|
||||
|
||||
// replace region
|
||||
endpoint = strings.Replace(endpoint, "{region}", string(region), 1)
|
||||
|
||||
// replace second level domain
|
||||
endpoint = strings.Replace(endpoint, "{secondLevelDomain}", region.secondLevelDomain(), 1)
|
||||
|
||||
return endpoint
|
||||
}
|
||||
|
||||
func (region Region) secondLevelDomain() string {
|
||||
if realmID, ok := regionRealm[region]; ok {
|
||||
if secondLevelDomain, ok := realm[realmID]; ok {
|
||||
return secondLevelDomain
|
||||
}
|
||||
}
|
||||
|
||||
Debugf("cannot find realm for region : %s, return default realm value.", region)
|
||||
return realm["oc1"]
|
||||
}
|
||||
|
||||
//StringToRegion convert a string to Region type
|
||||
func StringToRegion(stringRegion string) (r Region) {
|
||||
regionStr := strings.ToLower(stringRegion)
|
||||
// check if short region name provided
|
||||
if region, ok := shortNameRegion[regionStr]; ok {
|
||||
r = region
|
||||
return
|
||||
}
|
||||
// check if normal region name provided
|
||||
potentialRegion := Region(regionStr)
|
||||
if _, ok := regionRealm[potentialRegion]; ok {
|
||||
r = potentialRegion
|
||||
return
|
||||
}
|
||||
|
||||
Debugf("region named: %s, is not recognized from hard-coded region list, will check Region metadata info", stringRegion)
|
||||
r = checkAndAddRegionMetadata(stringRegion)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// canStringBeRegion test if the string can be a region, if it can, returns the string as is, otherwise it
|
||||
// returns an error
|
||||
var blankRegex = regexp.MustCompile("\\s")
|
||||
|
||||
func canStringBeRegion(stringRegion string) (region string, err error) {
|
||||
if blankRegex.MatchString(stringRegion) || stringRegion == "" {
|
||||
return "", fmt.Errorf("region can not be empty or have spaces")
|
||||
}
|
||||
return stringRegion, nil
|
||||
}
|
||||
|
||||
// check region info from original map
|
||||
func checkAndAddRegionMetadata(region string) Region {
|
||||
switch {
|
||||
case setRegionMetadataFromCfgFile(®ion):
|
||||
case setRegionMetadataFromEnvVar(®ion):
|
||||
case setRegionFromInstanceMetadataService(®ion):
|
||||
default:
|
||||
//err := fmt.Errorf("failed to get region metadata information.")
|
||||
return Region(region)
|
||||
}
|
||||
return Region(region)
|
||||
}
|
||||
|
||||
// EnableInstanceMetadataServiceLookup provides the interface to lookup IMDS region info
|
||||
func EnableInstanceMetadataServiceLookup() {
|
||||
Debugf("Set visitIMDS 'true' to enable IMDS Lookup.")
|
||||
visitIMDS = true
|
||||
}
|
||||
|
||||
// setRegionMetadataFromEnvVar checks if region metadata env variable is provided, once it's there, parse and added it
|
||||
// to region map, and it can make sure the env var can only be visited once.
|
||||
// Once successfully find the expected region(region name or short code), return true, region name will be stored in
|
||||
// the input pointer.
|
||||
func setRegionMetadataFromEnvVar(region *string) bool {
|
||||
if readEnvVar == false {
|
||||
Debugf("metadata region env variable had already been checked, no need to check again.")
|
||||
return false //no need to check it again.
|
||||
}
|
||||
// Mark readEnvVar Flag as false since it has already been visited.
|
||||
readEnvVar = false
|
||||
// check from env variable
|
||||
if jsonStr, existed := os.LookupEnv(regionMetadataEnvVarName); existed {
|
||||
Debugf("Raw content of region metadata env var:", jsonStr)
|
||||
var regionSchema map[string]string
|
||||
if err := json.Unmarshal([]byte(jsonStr), ®ionSchema); err != nil {
|
||||
Debugf("Can't unmarshal env var, the error info is", err)
|
||||
return false
|
||||
}
|
||||
// check if the specified region is in the env var.
|
||||
if checkSchemaItems(regionSchema) {
|
||||
// set mapping table
|
||||
addRegionSchema(regionSchema)
|
||||
if regionSchema[regionKeyPropertyName] == *region ||
|
||||
regionSchema[regionIdentifierPropertyName] == *region {
|
||||
*region = regionSchema[regionIdentifierPropertyName]
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Debugf("The Region Metadata Schema wasn't set in env variable - OCI_REGION_METADATA.")
|
||||
return false
|
||||
}
|
||||
|
||||
// setRegionMetadataFromCfgFile checks if region metadata config file is provided, once it's there, parse and add all
|
||||
// the valid regions to region map, the configuration file can only be visited once.
|
||||
// Once successfully find the expected region(region name or short code), return true, region name will be stored in
|
||||
// the input pointer.
|
||||
func setRegionMetadataFromCfgFile(region *string) bool {
|
||||
if readCfgFile == false {
|
||||
Debugf("metadata region config file had already been checked, no need to check again.")
|
||||
return false //no need to check it again.
|
||||
}
|
||||
// Mark readCfgFile Flag as false since it has already been visited.
|
||||
readCfgFile = false
|
||||
homeFolder := getHomeFolder()
|
||||
configFile := path.Join(homeFolder, regionMetadataCfgDirName, regionMetadataCfgFileName)
|
||||
if jsonArr, ok := readAndParseConfigFile(&configFile); ok {
|
||||
added := false
|
||||
for _, jsonItem := range jsonArr {
|
||||
if checkSchemaItems(jsonItem) {
|
||||
addRegionSchema(jsonItem)
|
||||
if jsonItem[regionKeyPropertyName] == *region ||
|
||||
jsonItem[regionIdentifierPropertyName] == *region {
|
||||
*region = jsonItem[regionIdentifierPropertyName]
|
||||
added = true
|
||||
}
|
||||
}
|
||||
}
|
||||
return added
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func readAndParseConfigFile(configFileName *string) (fileContent []map[string]string, ok bool) {
|
||||
|
||||
if content, err := ioutil.ReadFile(*configFileName); err == nil {
|
||||
Debugf("Raw content of region metadata config file content:", string(content[:]))
|
||||
if err := json.Unmarshal(content, &fileContent); err != nil {
|
||||
Debugf("Can't unmarshal config file, the error info is", err)
|
||||
return
|
||||
}
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
Debugf("No Region Metadata Config File provided.")
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// check map regionRealm's region name, if it's already there, no need to add it.
|
||||
func addRegionSchema(regionSchema map[string]string) {
|
||||
r := Region(strings.ToLower(regionSchema[regionIdentifierPropertyName]))
|
||||
if _, ok := regionRealm[r]; !ok {
|
||||
// set mapping table
|
||||
shortNameRegion[regionSchema[regionKeyPropertyName]] = r
|
||||
realm[regionSchema[realmKeyPropertyName]] = regionSchema[realmDomainComponentPropertyName]
|
||||
regionRealm[r] = regionSchema[realmKeyPropertyName]
|
||||
return
|
||||
}
|
||||
Debugf("Region {} has already been added, no need to add again.", regionSchema[regionIdentifierPropertyName])
|
||||
}
|
||||
|
||||
// check region schema content if all the required contents are provided
|
||||
func checkSchemaItems(regionSchema map[string]string) bool {
|
||||
if checkSchemaItem(regionSchema, regionIdentifierPropertyName) &&
|
||||
checkSchemaItem(regionSchema, realmKeyPropertyName) &&
|
||||
checkSchemaItem(regionSchema, realmDomainComponentPropertyName) &&
|
||||
checkSchemaItem(regionSchema, regionKeyPropertyName) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// check region schema item is valid, if so, convert it to lower case.
|
||||
func checkSchemaItem(regionSchema map[string]string, key string) bool {
|
||||
if val, ok := regionSchema[key]; ok {
|
||||
if val != "" {
|
||||
regionSchema[key] = strings.ToLower(val)
|
||||
return true
|
||||
}
|
||||
Debugf("Region metadata schema {} is provided,but content is empty.", key)
|
||||
return false
|
||||
}
|
||||
Debugf("Region metadata schema {} is not provided, please update the content", key)
|
||||
return false
|
||||
}
|
||||
|
||||
// setRegionFromInstanceMetadataService checks if region metadata can be provided from InstanceMetadataService.
|
||||
// Once successfully find the expected region(region name or short code), return true, region name will be stored in
|
||||
// the input pointer.
|
||||
// setRegionFromInstanceMetadataService will only be checked on the instance, by default it will not be enabled unless
|
||||
// user explicitly enable it.
|
||||
func setRegionFromInstanceMetadataService(region *string) bool {
|
||||
// example of content:
|
||||
// {
|
||||
// "realmKey" : "oc1",
|
||||
// "realmDomainComponent" : "oraclecloud.com",
|
||||
// "regionKey" : "YUL",
|
||||
// "regionIdentifier" : "ca-montreal-1"
|
||||
// }
|
||||
// Mark visitIMDS Flag as false since it has already been visited.
|
||||
if visitIMDS == false {
|
||||
Debugf("check from IMDS is disabled or IMDS had already been successfully visited, no need to check again.")
|
||||
return false
|
||||
}
|
||||
content, err := getRegionInfoFromInstanceMetadataService()
|
||||
if err != nil {
|
||||
Debugf("Failed to get instance metadata. Error: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
// Mark visitIMDS Flag as false since we have already successfully get the region info from IMDS.
|
||||
visitIMDS = false
|
||||
|
||||
var regionInfo map[string]string
|
||||
err = json.Unmarshal(content, ®ionInfo)
|
||||
if err != nil {
|
||||
Debugf("Failed to unmarshal the response content: %v \nError: %v", string(content), err)
|
||||
return false
|
||||
}
|
||||
|
||||
if checkSchemaItems(regionInfo) {
|
||||
addRegionSchema(regionInfo)
|
||||
if regionInfo[regionKeyPropertyName] == *region ||
|
||||
regionInfo[regionIdentifierPropertyName] == *region {
|
||||
*region = regionInfo[regionIdentifierPropertyName]
|
||||
}
|
||||
} else {
|
||||
Debugf("Region information is not valid.")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// getRegionInfoFromInstanceMetadataServiceProd calls instance metadata service and get the region information
|
||||
func getRegionInfoFromInstanceMetadataServiceProd() ([]byte, error) {
|
||||
request, err := http.NewRequest(http.MethodGet, instanceMetadataRegionInfoURLV2, nil)
|
||||
request.Header.Add("Authorization", "Bearer Oracle")
|
||||
|
||||
client := &http.Client{
|
||||
Timeout: time.Second * 10,
|
||||
}
|
||||
resp, err := client.Do(request)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to call instance metadata service. Error: %v", err)
|
||||
}
|
||||
|
||||
statusCode := resp.StatusCode
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
content, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to get region information from response body. Error: %v", err)
|
||||
}
|
||||
|
||||
if statusCode != http.StatusOK {
|
||||
err = fmt.Errorf("HTTP Get failed: URL: %s, Status: %s, Message: %s",
|
||||
instanceMetadataRegionInfoURLV2, resp.Status, string(content))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
|
@ -0,0 +1,659 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AuthenticationType for auth
|
||||
type AuthenticationType string
|
||||
|
||||
const (
|
||||
// UserPrincipal is default auth type
|
||||
UserPrincipal AuthenticationType = "user_principal"
|
||||
// InstancePrincipal is used for instance principle auth type
|
||||
InstancePrincipal AuthenticationType = "instance_principal"
|
||||
// InstancePrincipalDelegationToken is used for instance principle delegation token auth type
|
||||
InstancePrincipalDelegationToken AuthenticationType = "instance_principle_delegation_token"
|
||||
// UnknownAuthenticationType is used for none meaningful auth type
|
||||
UnknownAuthenticationType AuthenticationType = "unknown_auth_type"
|
||||
)
|
||||
|
||||
// AuthConfig is used for getting auth related paras in config file
|
||||
type AuthConfig struct {
|
||||
AuthType AuthenticationType
|
||||
// IsFromConfigFile is used to point out if the authConfig is from configuration file
|
||||
IsFromConfigFile bool
|
||||
OboToken *string
|
||||
}
|
||||
|
||||
// ConfigurationProvider wraps information about the account owner
|
||||
type ConfigurationProvider interface {
|
||||
KeyProvider
|
||||
TenancyOCID() (string, error)
|
||||
UserOCID() (string, error)
|
||||
KeyFingerprint() (string, error)
|
||||
Region() (string, error)
|
||||
// AuthType() is used for specify the needed auth type, like UserPrincipal, InstancePrincipal, etc.
|
||||
AuthType() (AuthConfig, error)
|
||||
}
|
||||
|
||||
// IsConfigurationProviderValid Tests all parts of the configuration provider do not return an error, this method will
|
||||
// not check AuthType(), since authType() is not required to be there.
|
||||
func IsConfigurationProviderValid(conf ConfigurationProvider) (ok bool, err error) {
|
||||
baseFn := []func() (string, error){conf.TenancyOCID, conf.UserOCID, conf.KeyFingerprint, conf.Region, conf.KeyID}
|
||||
for _, fn := range baseFn {
|
||||
_, err = fn()
|
||||
ok = err == nil
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
_, err = conf.PrivateRSAKey()
|
||||
ok = err == nil
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// rawConfigurationProvider allows a user to simply construct a configuration provider from raw values.
|
||||
type rawConfigurationProvider struct {
|
||||
tenancy string
|
||||
user string
|
||||
region string
|
||||
fingerprint string
|
||||
privateKey string
|
||||
privateKeyPassphrase *string
|
||||
}
|
||||
|
||||
// NewRawConfigurationProvider will create a ConfigurationProvider with the arguments of the function
|
||||
func NewRawConfigurationProvider(tenancy, user, region, fingerprint, privateKey string, privateKeyPassphrase *string) ConfigurationProvider {
|
||||
return rawConfigurationProvider{tenancy, user, region, fingerprint, privateKey, privateKeyPassphrase}
|
||||
}
|
||||
|
||||
func (p rawConfigurationProvider) PrivateRSAKey() (key *rsa.PrivateKey, err error) {
|
||||
return PrivateKeyFromBytes([]byte(p.privateKey), p.privateKeyPassphrase)
|
||||
}
|
||||
|
||||
func (p rawConfigurationProvider) KeyID() (keyID string, err error) {
|
||||
tenancy, err := p.TenancyOCID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := p.UserOCID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fingerprint, err := p.KeyFingerprint()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s/%s", tenancy, user, fingerprint), nil
|
||||
}
|
||||
|
||||
func (p rawConfigurationProvider) TenancyOCID() (string, error) {
|
||||
if p.tenancy == "" {
|
||||
return "", fmt.Errorf("tenancy OCID can not be empty")
|
||||
}
|
||||
return p.tenancy, nil
|
||||
}
|
||||
|
||||
func (p rawConfigurationProvider) UserOCID() (string, error) {
|
||||
if p.user == "" {
|
||||
return "", fmt.Errorf("user OCID can not be empty")
|
||||
}
|
||||
return p.user, nil
|
||||
}
|
||||
|
||||
func (p rawConfigurationProvider) KeyFingerprint() (string, error) {
|
||||
if p.fingerprint == "" {
|
||||
return "", fmt.Errorf("fingerprint can not be empty")
|
||||
}
|
||||
return p.fingerprint, nil
|
||||
}
|
||||
|
||||
func (p rawConfigurationProvider) Region() (string, error) {
|
||||
return canStringBeRegion(p.region)
|
||||
}
|
||||
|
||||
func (p rawConfigurationProvider) AuthType() (AuthConfig, error) {
|
||||
return AuthConfig{UnknownAuthenticationType, false, nil}, nil
|
||||
}
|
||||
|
||||
// environmentConfigurationProvider reads configuration from environment variables
|
||||
type environmentConfigurationProvider struct {
|
||||
PrivateKeyPassword string
|
||||
EnvironmentVariablePrefix string
|
||||
}
|
||||
|
||||
// ConfigurationProviderEnvironmentVariables creates a ConfigurationProvider from a uniform set of environment variables starting with a prefix
|
||||
// The env variables should look like: [prefix]_private_key_path, [prefix]_tenancy_ocid, [prefix]_user_ocid, [prefix]_fingerprint
|
||||
// [prefix]_region
|
||||
func ConfigurationProviderEnvironmentVariables(environmentVariablePrefix, privateKeyPassword string) ConfigurationProvider {
|
||||
return environmentConfigurationProvider{EnvironmentVariablePrefix: environmentVariablePrefix,
|
||||
PrivateKeyPassword: privateKeyPassword}
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) String() string {
|
||||
return fmt.Sprintf("Configuration provided by environment variables prefixed with: %s", p.EnvironmentVariablePrefix)
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) PrivateRSAKey() (key *rsa.PrivateKey, err error) {
|
||||
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "private_key_path")
|
||||
var ok bool
|
||||
var value string
|
||||
if value, ok = os.LookupEnv(environmentVariable); !ok {
|
||||
return nil, fmt.Errorf("can not read PrivateKey from env variable: %s", environmentVariable)
|
||||
}
|
||||
|
||||
expandedPath := expandPath(value)
|
||||
pemFileContent, err := ioutil.ReadFile(expandedPath)
|
||||
if err != nil {
|
||||
Debugln("Can not read PrivateKey location from environment variable: " + environmentVariable)
|
||||
return
|
||||
}
|
||||
|
||||
key, err = PrivateKeyFromBytes(pemFileContent, &p.PrivateKeyPassword)
|
||||
return
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) KeyID() (keyID string, err error) {
|
||||
ocid, err := p.TenancyOCID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
userocid, err := p.UserOCID()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fingerprint, err := p.KeyFingerprint()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s/%s/%s", ocid, userocid, fingerprint), nil
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) TenancyOCID() (value string, err error) {
|
||||
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "tenancy_ocid")
|
||||
var ok bool
|
||||
if value, ok = os.LookupEnv(environmentVariable); !ok {
|
||||
err = fmt.Errorf("can not read Tenancy from environment variable %s", environmentVariable)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) UserOCID() (value string, err error) {
|
||||
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "user_ocid")
|
||||
var ok bool
|
||||
if value, ok = os.LookupEnv(environmentVariable); !ok {
|
||||
err = fmt.Errorf("can not read user id from environment variable %s", environmentVariable)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) KeyFingerprint() (value string, err error) {
|
||||
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "fingerprint")
|
||||
var ok bool
|
||||
if value, ok = os.LookupEnv(environmentVariable); !ok {
|
||||
err = fmt.Errorf("can not read fingerprint from environment variable %s", environmentVariable)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) Region() (value string, err error) {
|
||||
environmentVariable := fmt.Sprintf("%s_%s", p.EnvironmentVariablePrefix, "region")
|
||||
var ok bool
|
||||
if value, ok = os.LookupEnv(environmentVariable); !ok {
|
||||
err = fmt.Errorf("can not read region from environment variable %s", environmentVariable)
|
||||
return value, err
|
||||
}
|
||||
|
||||
return canStringBeRegion(value)
|
||||
}
|
||||
|
||||
func (p environmentConfigurationProvider) AuthType() (AuthConfig, error) {
|
||||
return AuthConfig{UnknownAuthenticationType, false, nil},
|
||||
fmt.Errorf("unsupported, keep the interface")
|
||||
}
|
||||
|
||||
// fileConfigurationProvider. reads configuration information from a file
|
||||
type fileConfigurationProvider struct {
|
||||
//The path to the configuration file
|
||||
ConfigPath string
|
||||
|
||||
//The password for the private key
|
||||
PrivateKeyPassword string
|
||||
|
||||
//The profile for the configuration
|
||||
Profile string
|
||||
|
||||
//ConfigFileInfo
|
||||
FileInfo *configFileInfo
|
||||
}
|
||||
|
||||
// ConfigurationProviderFromFile creates a configuration provider from a configuration file
|
||||
// by reading the "DEFAULT" profile
|
||||
func ConfigurationProviderFromFile(configFilePath, privateKeyPassword string) (ConfigurationProvider, error) {
|
||||
if configFilePath == "" {
|
||||
return nil, fmt.Errorf("config file path can not be empty")
|
||||
}
|
||||
|
||||
return fileConfigurationProvider{
|
||||
ConfigPath: configFilePath,
|
||||
PrivateKeyPassword: privateKeyPassword,
|
||||
Profile: "DEFAULT"}, nil
|
||||
}
|
||||
|
||||
// ConfigurationProviderFromFileWithProfile creates a configuration provider from a configuration file
|
||||
// and the given profile
|
||||
func ConfigurationProviderFromFileWithProfile(configFilePath, profile, privateKeyPassword string) (ConfigurationProvider, error) {
|
||||
if configFilePath == "" {
|
||||
return nil, fmt.Errorf("config file path can not be empty")
|
||||
}
|
||||
|
||||
return fileConfigurationProvider{
|
||||
ConfigPath: configFilePath,
|
||||
PrivateKeyPassword: privateKeyPassword,
|
||||
Profile: profile}, nil
|
||||
}
|
||||
|
||||
type configFileInfo struct {
|
||||
UserOcid, Fingerprint, KeyFilePath, TenancyOcid, Region, Passphrase, SecurityTokenFilePath, DelegationTokenFilePath,
|
||||
AuthenticationType string
|
||||
PresentConfiguration rune
|
||||
}
|
||||
|
||||
const (
|
||||
hasTenancy = 1 << iota
|
||||
hasUser
|
||||
hasFingerprint
|
||||
hasRegion
|
||||
hasKeyFile
|
||||
hasPassphrase
|
||||
hasSecurityTokenFile
|
||||
hasDelegationTokenFile
|
||||
hasAuthenticationType
|
||||
none
|
||||
)
|
||||
|
||||
var profileRegex = regexp.MustCompile(`^\[(.*)\]`)
|
||||
|
||||
func parseConfigFile(data []byte, profile string) (info *configFileInfo, err error) {
|
||||
|
||||
if len(data) == 0 {
|
||||
return nil, fmt.Errorf("configuration file content is empty")
|
||||
}
|
||||
|
||||
content := string(data)
|
||||
splitContent := strings.Split(content, "\n")
|
||||
|
||||
//Look for profile
|
||||
for i, line := range splitContent {
|
||||
if match := profileRegex.FindStringSubmatch(line); match != nil && len(match) > 1 && match[1] == profile {
|
||||
start := i + 1
|
||||
return parseConfigAtLine(start, splitContent)
|
||||
}
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("configuration file did not contain profile: %s", profile)
|
||||
}
|
||||
|
||||
func parseConfigAtLine(start int, content []string) (info *configFileInfo, err error) {
|
||||
var configurationPresent rune
|
||||
info = &configFileInfo{}
|
||||
for i := start; i < len(content); i++ {
|
||||
line := content[i]
|
||||
if profileRegex.MatchString(line) {
|
||||
break
|
||||
}
|
||||
|
||||
if !strings.Contains(line, "=") {
|
||||
continue
|
||||
}
|
||||
|
||||
splits := strings.Split(line, "=")
|
||||
switch key, value := strings.TrimSpace(splits[0]), strings.TrimSpace(splits[1]); strings.ToLower(key) {
|
||||
case "passphrase", "pass_phrase":
|
||||
configurationPresent = configurationPresent | hasPassphrase
|
||||
info.Passphrase = value
|
||||
case "user":
|
||||
configurationPresent = configurationPresent | hasUser
|
||||
info.UserOcid = value
|
||||
case "fingerprint":
|
||||
configurationPresent = configurationPresent | hasFingerprint
|
||||
info.Fingerprint = value
|
||||
case "key_file":
|
||||
configurationPresent = configurationPresent | hasKeyFile
|
||||
info.KeyFilePath = value
|
||||
case "tenancy":
|
||||
configurationPresent = configurationPresent | hasTenancy
|
||||
info.TenancyOcid = value
|
||||
case "region":
|
||||
configurationPresent = configurationPresent | hasRegion
|
||||
info.Region = value
|
||||
case "security_token_file":
|
||||
configurationPresent = configurationPresent | hasSecurityTokenFile
|
||||
info.SecurityTokenFilePath = value
|
||||
case "delegation_token_file":
|
||||
configurationPresent = configurationPresent | hasDelegationTokenFile
|
||||
info.DelegationTokenFilePath = value
|
||||
case "authentication_type":
|
||||
configurationPresent = configurationPresent | hasAuthenticationType
|
||||
info.AuthenticationType = value
|
||||
}
|
||||
}
|
||||
info.PresentConfiguration = configurationPresent
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// cleans and expands the path if it contains a tilde , returns the expanded path or the input path as is if not expansion
|
||||
// was performed
|
||||
func expandPath(filepath string) (expandedPath string) {
|
||||
cleanedPath := path.Clean(filepath)
|
||||
expandedPath = cleanedPath
|
||||
if strings.HasPrefix(cleanedPath, "~") {
|
||||
rest := cleanedPath[2:]
|
||||
expandedPath = path.Join(getHomeFolder(), rest)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func openConfigFile(configFilePath string) (data []byte, err error) {
|
||||
expandedPath := expandPath(configFilePath)
|
||||
data, err = ioutil.ReadFile(expandedPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read config file: %s due to: %s", configFilePath, err.Error())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) String() string {
|
||||
return fmt.Sprintf("Configuration provided by file: %s", p.ConfigPath)
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) readAndParseConfigFile() (info *configFileInfo, err error) {
|
||||
if p.FileInfo != nil {
|
||||
return p.FileInfo, nil
|
||||
}
|
||||
|
||||
if p.ConfigPath == "" {
|
||||
return nil, fmt.Errorf("configuration path can not be empty")
|
||||
}
|
||||
|
||||
data, err := openConfigFile(p.ConfigPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error while parsing config file: %s. Due to: %s", p.ConfigPath, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
p.FileInfo, err = parseConfigFile(data, p.Profile)
|
||||
return p.FileInfo, err
|
||||
}
|
||||
|
||||
func presentOrError(value string, expectedConf, presentConf rune, confMissing string) (string, error) {
|
||||
if presentConf&expectedConf == expectedConf {
|
||||
return value, nil
|
||||
}
|
||||
return "", errors.New(confMissing + " configuration is missing from file")
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) TenancyOCID() (value string, err error) {
|
||||
info, err := p.readAndParseConfigFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
value, err = presentOrError(info.TenancyOcid, hasTenancy, info.PresentConfiguration, "tenancy")
|
||||
return
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) UserOCID() (value string, err error) {
|
||||
info, err := p.readAndParseConfigFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if value, err = presentOrError(info.UserOcid, hasUser, info.PresentConfiguration, "user"); err != nil {
|
||||
// need to check if securityTokenPath is provided, if security token is provided, userOCID can be "".
|
||||
if _, stErr := presentOrError(info.SecurityTokenFilePath, hasSecurityTokenFile, info.PresentConfiguration,
|
||||
"securityTokenPath"); stErr == nil {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) KeyFingerprint() (value string, err error) {
|
||||
info, err := p.readAndParseConfigFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
value, err = presentOrError(info.Fingerprint, hasFingerprint, info.PresentConfiguration, "fingerprint")
|
||||
return
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) KeyID() (keyID string, err error) {
|
||||
info, err := p.readAndParseConfigFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
if info.PresentConfiguration&hasUser == hasUser {
|
||||
return fmt.Sprintf("%s/%s/%s", info.TenancyOcid, info.UserOcid, info.Fingerprint), nil
|
||||
}
|
||||
if filePath, err := presentOrError(info.SecurityTokenFilePath, hasSecurityTokenFile, info.PresentConfiguration, "securityTokenFilePath"); err == nil {
|
||||
rawString, err := getTokenContent(filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return "ST$" + rawString, nil
|
||||
}
|
||||
err = fmt.Errorf("can not read SecurityTokenFilePath from configuration file due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) PrivateRSAKey() (key *rsa.PrivateKey, err error) {
|
||||
info, err := p.readAndParseConfigFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
filePath, err := presentOrError(info.KeyFilePath, hasKeyFile, info.PresentConfiguration, "key file path")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
expandedPath := expandPath(filePath)
|
||||
pemFileContent, err := ioutil.ReadFile(expandedPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read PrivateKey from configuration file due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
password := p.PrivateKeyPassword
|
||||
|
||||
if password == "" && ((info.PresentConfiguration & hasPassphrase) == hasPassphrase) {
|
||||
password = info.Passphrase
|
||||
}
|
||||
|
||||
key, err = PrivateKeyFromBytes(pemFileContent, &password)
|
||||
return
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) Region() (value string, err error) {
|
||||
info, err := p.readAndParseConfigFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read region configuration due to: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
value, err = presentOrError(info.Region, hasRegion, info.PresentConfiguration, "region")
|
||||
if err != nil {
|
||||
val, error := getRegionFromEnvVar()
|
||||
if error != nil {
|
||||
err = fmt.Errorf("region configuration is missing from file, nor for OCI_REGION env var")
|
||||
return
|
||||
}
|
||||
value = val
|
||||
}
|
||||
|
||||
return canStringBeRegion(value)
|
||||
}
|
||||
|
||||
func (p fileConfigurationProvider) AuthType() (AuthConfig, error) {
|
||||
info, err := p.readAndParseConfigFile()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read tenancy configuration due to: %s", err.Error())
|
||||
return AuthConfig{UnknownAuthenticationType, true, nil}, err
|
||||
}
|
||||
val, err := presentOrError(info.AuthenticationType, hasAuthenticationType, info.PresentConfiguration, "authentication_type")
|
||||
|
||||
if val == "instance_principal" {
|
||||
if filePath, err := presentOrError(info.DelegationTokenFilePath, hasDelegationTokenFile, info.PresentConfiguration, "delegationTokenFilePath"); err == nil {
|
||||
if delegationToken, err := getTokenContent(filePath); err == nil && delegationToken != "" {
|
||||
Debugf("delegation token content is %s, and error is %s ", delegationToken, err)
|
||||
return AuthConfig{InstancePrincipalDelegationToken, true, &delegationToken}, nil
|
||||
}
|
||||
return AuthConfig{UnknownAuthenticationType, true, nil}, err
|
||||
|
||||
}
|
||||
// normal instance principle
|
||||
return AuthConfig{InstancePrincipal, true, nil}, nil
|
||||
}
|
||||
|
||||
// by default, if no "authentication_type" is provided, just treated as user principle type, and will not return error
|
||||
return AuthConfig{UserPrincipal, true, nil}, nil
|
||||
}
|
||||
|
||||
func getTokenContent(filePath string) (string, error) {
|
||||
expandedPath := expandPath(filePath)
|
||||
tokenFileContent, err := ioutil.ReadFile(expandedPath)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("can not read token content from configuration file due to: %s", err.Error())
|
||||
return "", err
|
||||
}
|
||||
return fmt.Sprintf("%s", tokenFileContent), nil
|
||||
}
|
||||
|
||||
// A configuration provider that look for information in multiple configuration providers
|
||||
type composingConfigurationProvider struct {
|
||||
Providers []ConfigurationProvider
|
||||
}
|
||||
|
||||
// ComposingConfigurationProvider creates a composing configuration provider with the given slice of configuration providers
|
||||
// A composing provider will return the configuration of the first provider that has the required property
|
||||
// if no provider has the property it will return an error.
|
||||
func ComposingConfigurationProvider(providers []ConfigurationProvider) (ConfigurationProvider, error) {
|
||||
if len(providers) == 0 {
|
||||
return nil, fmt.Errorf("providers can not be an empty slice")
|
||||
}
|
||||
|
||||
for i, p := range providers {
|
||||
if p == nil {
|
||||
return nil, fmt.Errorf("provider in position: %d is nil. ComposingConfiurationProvider does not support nil values", i)
|
||||
}
|
||||
}
|
||||
return composingConfigurationProvider{Providers: providers}, nil
|
||||
}
|
||||
|
||||
func (c composingConfigurationProvider) TenancyOCID() (string, error) {
|
||||
for _, p := range c.Providers {
|
||||
val, err := p.TenancyOCID()
|
||||
if err == nil {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("did not find a proper configuration for tenancy")
|
||||
}
|
||||
|
||||
func (c composingConfigurationProvider) UserOCID() (string, error) {
|
||||
for _, p := range c.Providers {
|
||||
val, err := p.UserOCID()
|
||||
if err == nil {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("did not find a proper configuration for user")
|
||||
}
|
||||
|
||||
func (c composingConfigurationProvider) KeyFingerprint() (string, error) {
|
||||
for _, p := range c.Providers {
|
||||
val, err := p.KeyFingerprint()
|
||||
if err == nil {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("did not find a proper configuration for keyFingerprint")
|
||||
}
|
||||
func (c composingConfigurationProvider) Region() (string, error) {
|
||||
for _, p := range c.Providers {
|
||||
val, err := p.Region()
|
||||
if err == nil {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
if val, err := getRegionFromEnvVar(); err == nil {
|
||||
return val, nil
|
||||
}
|
||||
return "", fmt.Errorf("did not find a proper configuration for region, nor for OCI_REGION env var")
|
||||
}
|
||||
|
||||
func (c composingConfigurationProvider) KeyID() (string, error) {
|
||||
for _, p := range c.Providers {
|
||||
val, err := p.KeyID()
|
||||
if err == nil {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("did not find a proper configuration for key id")
|
||||
}
|
||||
|
||||
func (c composingConfigurationProvider) PrivateRSAKey() (*rsa.PrivateKey, error) {
|
||||
for _, p := range c.Providers {
|
||||
val, err := p.PrivateRSAKey()
|
||||
if err == nil {
|
||||
return val, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("did not find a proper configuration for private key")
|
||||
}
|
||||
|
||||
func (c composingConfigurationProvider) AuthType() (AuthConfig, error) {
|
||||
// only check the first default fileConfigProvider
|
||||
authConfig, err := c.Providers[0].AuthType()
|
||||
if err == nil && authConfig.AuthType != UnknownAuthenticationType {
|
||||
return authConfig, nil
|
||||
}
|
||||
return AuthConfig{UnknownAuthenticationType, false, nil}, fmt.Errorf("did not find a proper configuration for auth type")
|
||||
}
|
||||
|
||||
func getRegionFromEnvVar() (string, error) {
|
||||
regionEnvVar := "OCI_REGION"
|
||||
if region, existed := os.LookupEnv(regionEnvVar); existed {
|
||||
return region, nil
|
||||
}
|
||||
return "", fmt.Errorf("did not find OCI_REGION env var")
|
||||
}
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ServiceError models all potential errors generated the service call
|
||||
type ServiceError interface {
|
||||
// The http status code of the error
|
||||
GetHTTPStatusCode() int
|
||||
|
||||
// The human-readable error string as sent by the service
|
||||
GetMessage() string
|
||||
|
||||
// A short error code that defines the error, meant for programmatic parsing.
|
||||
// See https://docs.cloud.oracle.com/Content/API/References/apierrors.htm
|
||||
GetCode() string
|
||||
|
||||
// Unique Oracle-assigned identifier for the request.
|
||||
// If you need to contact Oracle about a particular request, please provide the request ID.
|
||||
GetOpcRequestID() string
|
||||
}
|
||||
|
||||
type servicefailure struct {
|
||||
StatusCode int
|
||||
Code string `json:"code,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
OpcRequestID string `json:"opc-request-id"`
|
||||
}
|
||||
|
||||
func newServiceFailureFromResponse(response *http.Response) error {
|
||||
var err error
|
||||
|
||||
se := servicefailure{
|
||||
StatusCode: response.StatusCode,
|
||||
Code: "BadErrorResponse",
|
||||
OpcRequestID: response.Header.Get("opc-request-id")}
|
||||
|
||||
//If there is an error consume the body, entirely
|
||||
body, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
se.Message = fmt.Sprintf("The body of the response was not readable, due to :%s", err.Error())
|
||||
return se
|
||||
}
|
||||
|
||||
err = json.Unmarshal(body, &se)
|
||||
if err != nil {
|
||||
Debugf("Error response could not be parsed due to: %s", err.Error())
|
||||
se.Message = fmt.Sprintf("Failed to parse json from response body due to: %s. With response body %s.", err.Error(), string(body[:]))
|
||||
return se
|
||||
}
|
||||
return se
|
||||
}
|
||||
|
||||
func (se servicefailure) Error() string {
|
||||
return fmt.Sprintf("Service error:%s. %s. http status code: %d. Opc request id: %s",
|
||||
se.Code, se.Message, se.StatusCode, se.OpcRequestID)
|
||||
}
|
||||
|
||||
func (se servicefailure) GetHTTPStatusCode() int {
|
||||
return se.StatusCode
|
||||
|
||||
}
|
||||
|
||||
func (se servicefailure) GetMessage() string {
|
||||
return se.Message
|
||||
}
|
||||
|
||||
func (se servicefailure) GetCode() string {
|
||||
return se.Code
|
||||
}
|
||||
|
||||
func (se servicefailure) GetOpcRequestID() string {
|
||||
return se.OpcRequestID
|
||||
}
|
||||
|
||||
// IsServiceError returns false if the error is not service side, otherwise true
|
||||
// additionally it returns an interface representing the ServiceError
|
||||
func IsServiceError(err error) (failure ServiceError, ok bool) {
|
||||
failure, ok = err.(servicefailure)
|
||||
return
|
||||
}
|
||||
|
||||
type deadlineExceededByBackoffError struct{}
|
||||
|
||||
func (deadlineExceededByBackoffError) Error() string {
|
||||
return "now() + computed backoff duration exceeds request deadline"
|
||||
}
|
||||
|
||||
// DeadlineExceededByBackoff is the error returned by Call() when GetNextDuration() returns a time.Duration that would
|
||||
// force the user to wait past the request deadline before re-issuing a request. This enables us to exit early, since
|
||||
// we cannot succeed based on the configured retry policy.
|
||||
var DeadlineExceededByBackoff error = deadlineExceededByBackoffError{}
|
||||
|
||||
// NonSeekableRequestRetryFailure is the error returned when the request is with binary request body, and is configured
|
||||
// retry, but the request body is not retryable
|
||||
type NonSeekableRequestRetryFailure struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (ne NonSeekableRequestRetryFailure) Error() string {
|
||||
if ne.err == nil {
|
||||
return fmt.Sprintf("Unable to perform Retry on this request body type, which did not implement seek() interface")
|
||||
}
|
||||
return fmt.Sprintf("%s. Unable to perform Retry on this request body type, which did not implement seek() interface", ne.err.Error())
|
||||
}
|
||||
|
||||
// IsNetworkError validatas if an error is a net.Error and check if it's temporary or timeout
|
||||
func IsNetworkError(err error) bool {
|
||||
if r, ok := err.(net.Error); ok && (r.Temporary() || r.Timeout()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/x509"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// String returns a pointer to the provided string
|
||||
func String(value string) *string {
|
||||
return &value
|
||||
}
|
||||
|
||||
// Int returns a pointer to the provided int
|
||||
func Int(value int) *int {
|
||||
return &value
|
||||
}
|
||||
|
||||
// Int64 returns a pointer to the provided int64
|
||||
func Int64(value int64) *int64 {
|
||||
return &value
|
||||
}
|
||||
|
||||
// Uint returns a pointer to the provided uint
|
||||
func Uint(value uint) *uint {
|
||||
return &value
|
||||
}
|
||||
|
||||
//Float32 returns a pointer to the provided float32
|
||||
func Float32(value float32) *float32 {
|
||||
return &value
|
||||
}
|
||||
|
||||
//Float64 returns a pointer to the provided float64
|
||||
func Float64(value float64) *float64 {
|
||||
return &value
|
||||
}
|
||||
|
||||
//Bool returns a pointer to the provided bool
|
||||
func Bool(value bool) *bool {
|
||||
return &value
|
||||
}
|
||||
|
||||
//PointerString prints the values of pointers in a struct
|
||||
//Producing a human friendly string for an struct with pointers.
|
||||
//useful when debugging the values of a struct
|
||||
func PointerString(datastruct interface{}) (representation string) {
|
||||
val := reflect.ValueOf(datastruct)
|
||||
typ := reflect.TypeOf(datastruct)
|
||||
all := make([]string, 2)
|
||||
all = append(all, "{")
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
sf := typ.Field(i)
|
||||
|
||||
//unexported
|
||||
if sf.PkgPath != "" && !sf.Anonymous {
|
||||
continue
|
||||
}
|
||||
|
||||
sv := val.Field(i)
|
||||
stringValue := ""
|
||||
if isNil(sv) {
|
||||
stringValue = fmt.Sprintf("%s=<nil>", sf.Name)
|
||||
} else {
|
||||
if sv.Type().Kind() == reflect.Ptr {
|
||||
sv = sv.Elem()
|
||||
}
|
||||
stringValue = fmt.Sprintf("%s=%v", sf.Name, sv)
|
||||
}
|
||||
all = append(all, stringValue)
|
||||
}
|
||||
all = append(all, "}")
|
||||
representation = strings.TrimSpace(strings.Join(all, " "))
|
||||
return
|
||||
}
|
||||
|
||||
// SDKTime a struct that parses/renders to/from json using RFC339 date-time information
|
||||
type SDKTime struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
// SDKDate a struct that parses/renders to/from json using only date information
|
||||
type SDKDate struct {
|
||||
//Date date information
|
||||
Date time.Time
|
||||
}
|
||||
|
||||
func sdkTimeFromTime(t time.Time) SDKTime {
|
||||
return SDKTime{t}
|
||||
}
|
||||
|
||||
func sdkDateFromTime(t time.Time) SDKDate {
|
||||
return SDKDate{Date: t}
|
||||
}
|
||||
|
||||
func formatTime(t SDKTime) string {
|
||||
return t.Format(sdkTimeFormat)
|
||||
}
|
||||
|
||||
func formatDate(t SDKDate) string {
|
||||
return t.Date.Format(sdkDateFormat)
|
||||
}
|
||||
|
||||
func now() *SDKTime {
|
||||
t := SDKTime{time.Now()}
|
||||
return &t
|
||||
}
|
||||
|
||||
var timeType = reflect.TypeOf(SDKTime{})
|
||||
var timeTypePtr = reflect.TypeOf(&SDKTime{})
|
||||
|
||||
var sdkDateType = reflect.TypeOf(SDKDate{})
|
||||
var sdkDateTypePtr = reflect.TypeOf(&SDKDate{})
|
||||
|
||||
//Formats for sdk supported time representations
|
||||
const sdkTimeFormat = time.RFC3339Nano
|
||||
const rfc1123OptionalLeadingDigitsInDay = "Mon, _2 Jan 2006 15:04:05 MST"
|
||||
const sdkDateFormat = "2006-01-02"
|
||||
|
||||
func tryParsingTimeWithValidFormatsForHeaders(data []byte, headerName string) (t time.Time, err error) {
|
||||
header := strings.ToLower(headerName)
|
||||
switch header {
|
||||
case "lastmodified", "date":
|
||||
t, err = tryParsing(data, time.RFC3339Nano, time.RFC3339, time.RFC1123, rfc1123OptionalLeadingDigitsInDay, time.RFC850, time.ANSIC)
|
||||
return
|
||||
default: //By default we parse with RFC3339
|
||||
t, err = time.Parse(sdkTimeFormat, string(data))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func tryParsing(data []byte, layouts ...string) (tm time.Time, err error) {
|
||||
datestring := string(data)
|
||||
for _, l := range layouts {
|
||||
tm, err = time.Parse(l, datestring)
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = fmt.Errorf("Could not parse time: %s with formats: %s", datestring, layouts[:])
|
||||
return
|
||||
}
|
||||
|
||||
// String returns string representation of SDKDate
|
||||
func (t *SDKDate) String() string {
|
||||
return t.Date.Format(sdkDateFormat)
|
||||
}
|
||||
|
||||
// NewSDKDateFromString parses the dateString into SDKDate
|
||||
func NewSDKDateFromString(dateString string) (*SDKDate, error) {
|
||||
parsedTime, err := time.Parse(sdkDateFormat, dateString)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &SDKDate{Date: parsedTime}, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from json
|
||||
func (t *SDKTime) UnmarshalJSON(data []byte) (e error) {
|
||||
s := string(data)
|
||||
if s == "null" {
|
||||
t.Time = time.Time{}
|
||||
} else {
|
||||
//Try parsing with RFC3339
|
||||
t.Time, e = time.Parse(`"`+sdkTimeFormat+`"`, string(data))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalJSON marshals to JSON
|
||||
func (t *SDKTime) MarshalJSON() (buff []byte, e error) {
|
||||
s := t.Format(sdkTimeFormat)
|
||||
buff = []byte(`"` + s + `"`)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from json
|
||||
func (t *SDKDate) UnmarshalJSON(data []byte) (e error) {
|
||||
if string(data) == `"null"` {
|
||||
t.Date = time.Time{}
|
||||
return
|
||||
}
|
||||
|
||||
t.Date, e = tryParsing(data,
|
||||
strconv.Quote(sdkDateFormat),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalJSON marshals to JSON
|
||||
func (t *SDKDate) MarshalJSON() (buff []byte, e error) {
|
||||
s := t.Date.Format(sdkDateFormat)
|
||||
buff = []byte(strconv.Quote(s))
|
||||
return
|
||||
}
|
||||
|
||||
// PrivateKeyFromBytes is a helper function that will produce a RSA private
|
||||
// key from bytes. This function is deprecated in favour of PrivateKeyFromBytesWithPassword
|
||||
// Deprecated
|
||||
func PrivateKeyFromBytes(pemData []byte, password *string) (key *rsa.PrivateKey, e error) {
|
||||
if password == nil {
|
||||
return PrivateKeyFromBytesWithPassword(pemData, nil)
|
||||
}
|
||||
|
||||
return PrivateKeyFromBytesWithPassword(pemData, []byte(*password))
|
||||
}
|
||||
|
||||
// PrivateKeyFromBytesWithPassword is a helper function that will produce a RSA private
|
||||
// key from bytes and a password.
|
||||
func PrivateKeyFromBytesWithPassword(pemData, password []byte) (key *rsa.PrivateKey, e error) {
|
||||
if pemBlock, _ := pem.Decode(pemData); pemBlock != nil {
|
||||
decrypted := pemBlock.Bytes
|
||||
if x509.IsEncryptedPEMBlock(pemBlock) {
|
||||
if password == nil {
|
||||
e = fmt.Errorf("private key password is required for encrypted private keys")
|
||||
return
|
||||
}
|
||||
if decrypted, e = x509.DecryptPEMBlock(pemBlock, password); e != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
key, e = parsePKCSPrivateKey(decrypted)
|
||||
|
||||
} else {
|
||||
e = fmt.Errorf("PEM data was not found in buffer")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ParsePrivateKey using PKCS1 or PKCS8
|
||||
func parsePKCSPrivateKey(decryptedKey []byte) (*rsa.PrivateKey, error) {
|
||||
if key, err := x509.ParsePKCS1PrivateKey(decryptedKey); err == nil {
|
||||
return key, nil
|
||||
}
|
||||
if key, err := x509.ParsePKCS8PrivateKey(decryptedKey); err == nil {
|
||||
switch key := key.(type) {
|
||||
case *rsa.PrivateKey:
|
||||
return key, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupportesd private key type in PKCS8 wrapping")
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("failed to parse private key")
|
||||
}
|
||||
|
||||
// parseContentLength trims whitespace from cl and returns -1 if can't purse uint, or the value if it's no less than 0
|
||||
func parseContentLength(cl string) int64 {
|
||||
cl = textproto.TrimString(cl)
|
||||
n, err := strconv.ParseUint(cl, 10, 63)
|
||||
if err != nil {
|
||||
return -1
|
||||
}
|
||||
return int64(n)
|
||||
}
|
||||
|
||||
func generateRandUUID() (string, error) {
|
||||
b := make([]byte, 16)
|
||||
_, err := rand.Read(b)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
uuid := fmt.Sprintf("%x%x%x%x%x", b[0:4], b[4:6], b[6:8], b[8:10], b[10:])
|
||||
|
||||
return uuid, nil
|
||||
}
|
||||
|
||||
func makeACopy(original []string) []string {
|
||||
tmp := make([]string, len(original))
|
||||
copy(tmp, original)
|
||||
return tmp
|
||||
}
|
||||
|
||||
// getExpectHeaderConfig is used for checking if Expect header Env var is explicitly set to false, otherwise would add
|
||||
// the header by default
|
||||
func getExpectHeaderConfig() bool {
|
||||
if val, existed := os.LookupEnv(usingExpectHeaderEnvVar); existed && val == "FALSE" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,270 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// HTTPRequestSigner the interface to sign a request
|
||||
type HTTPRequestSigner interface {
|
||||
Sign(r *http.Request) error
|
||||
}
|
||||
|
||||
// KeyProvider interface that wraps information about the key's account owner
|
||||
type KeyProvider interface {
|
||||
PrivateRSAKey() (*rsa.PrivateKey, error)
|
||||
KeyID() (string, error)
|
||||
}
|
||||
|
||||
const signerVersion = "1"
|
||||
|
||||
// SignerBodyHashPredicate a function that allows to disable/enable body hashing
|
||||
// of requests and headers associated with body content
|
||||
type SignerBodyHashPredicate func(r *http.Request) bool
|
||||
|
||||
// ociRequestSigner implements the http-signatures-draft spec
|
||||
// as described in https://tools.ietf.org/html/draft-cavage-http-signatures-08
|
||||
type ociRequestSigner struct {
|
||||
KeyProvider KeyProvider
|
||||
GenericHeaders []string
|
||||
BodyHeaders []string
|
||||
ShouldHashBody SignerBodyHashPredicate
|
||||
}
|
||||
|
||||
var (
|
||||
defaultGenericHeaders = []string{"date", "(request-target)", "host"}
|
||||
defaultBodyHeaders = []string{"content-length", "content-type", "x-content-sha256"}
|
||||
defaultBodyHashPredicate = func(r *http.Request) bool {
|
||||
return r.Method == http.MethodPost || r.Method == http.MethodPut || r.Method == http.MethodPatch
|
||||
}
|
||||
)
|
||||
|
||||
// DefaultGenericHeaders list of default generic headers that is used in signing
|
||||
func DefaultGenericHeaders() []string {
|
||||
return makeACopy(defaultGenericHeaders)
|
||||
}
|
||||
|
||||
// DefaultBodyHeaders list of default body headers that is used in signing
|
||||
func DefaultBodyHeaders() []string {
|
||||
return makeACopy(defaultBodyHeaders)
|
||||
}
|
||||
|
||||
// DefaultRequestSigner creates a signer with default parameters.
|
||||
func DefaultRequestSigner(provider KeyProvider) HTTPRequestSigner {
|
||||
return RequestSigner(provider, defaultGenericHeaders, defaultBodyHeaders)
|
||||
}
|
||||
|
||||
// RequestSignerExcludeBody creates a signer without hash the body.
|
||||
func RequestSignerExcludeBody(provider KeyProvider) HTTPRequestSigner {
|
||||
bodyHashPredicate := func(r *http.Request) bool {
|
||||
// week request signer will not hash the body
|
||||
return false
|
||||
}
|
||||
return RequestSignerWithBodyHashingPredicate(provider, defaultGenericHeaders, defaultBodyHeaders, bodyHashPredicate)
|
||||
}
|
||||
|
||||
// NewSignerFromOCIRequestSigner creates a copy of the request signer and attaches the new SignerBodyHashPredicate
|
||||
// returns an error if the passed signer is not of type ociRequestSigner
|
||||
func NewSignerFromOCIRequestSigner(oldSigner HTTPRequestSigner, predicate SignerBodyHashPredicate) (HTTPRequestSigner, error) {
|
||||
if oldS, ok := oldSigner.(ociRequestSigner); ok {
|
||||
s := ociRequestSigner{
|
||||
KeyProvider: oldS.KeyProvider,
|
||||
GenericHeaders: oldS.GenericHeaders,
|
||||
BodyHeaders: oldS.BodyHeaders,
|
||||
ShouldHashBody: predicate,
|
||||
}
|
||||
return s, nil
|
||||
|
||||
}
|
||||
return nil, fmt.Errorf("can not create a signer, input signer needs to be of type ociRequestSigner")
|
||||
}
|
||||
|
||||
// RequestSigner creates a signer that utilizes the specified headers for signing
|
||||
// and the default predicate for using the body of the request as part of the signature
|
||||
func RequestSigner(provider KeyProvider, genericHeaders, bodyHeaders []string) HTTPRequestSigner {
|
||||
return ociRequestSigner{
|
||||
KeyProvider: provider,
|
||||
GenericHeaders: genericHeaders,
|
||||
BodyHeaders: bodyHeaders,
|
||||
ShouldHashBody: defaultBodyHashPredicate}
|
||||
}
|
||||
|
||||
// RequestSignerWithBodyHashingPredicate creates a signer that utilizes the specified headers for signing, as well as a predicate for using
|
||||
// the body of the request and bodyHeaders parameter as part of the signature
|
||||
func RequestSignerWithBodyHashingPredicate(provider KeyProvider, genericHeaders, bodyHeaders []string, shouldHashBody SignerBodyHashPredicate) HTTPRequestSigner {
|
||||
return ociRequestSigner{
|
||||
KeyProvider: provider,
|
||||
GenericHeaders: genericHeaders,
|
||||
BodyHeaders: bodyHeaders,
|
||||
ShouldHashBody: shouldHashBody}
|
||||
}
|
||||
|
||||
func (signer ociRequestSigner) getSigningHeaders(r *http.Request) []string {
|
||||
var result []string
|
||||
result = append(result, signer.GenericHeaders...)
|
||||
|
||||
if signer.ShouldHashBody(r) {
|
||||
result = append(result, signer.BodyHeaders...)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (signer ociRequestSigner) getSigningString(request *http.Request) string {
|
||||
signingHeaders := signer.getSigningHeaders(request)
|
||||
signingParts := make([]string, len(signingHeaders))
|
||||
for i, part := range signingHeaders {
|
||||
var value string
|
||||
part = strings.ToLower(part)
|
||||
switch part {
|
||||
case "(request-target)":
|
||||
value = getRequestTarget(request)
|
||||
case "host":
|
||||
value = request.URL.Host
|
||||
if len(value) == 0 {
|
||||
value = request.Host
|
||||
}
|
||||
default:
|
||||
value = request.Header.Get(part)
|
||||
}
|
||||
signingParts[i] = fmt.Sprintf("%s: %s", part, value)
|
||||
}
|
||||
|
||||
signingString := strings.Join(signingParts, "\n")
|
||||
return signingString
|
||||
|
||||
}
|
||||
|
||||
func getRequestTarget(request *http.Request) string {
|
||||
lowercaseMethod := strings.ToLower(request.Method)
|
||||
return fmt.Sprintf("%s %s", lowercaseMethod, request.URL.RequestURI())
|
||||
}
|
||||
|
||||
func calculateHashOfBody(request *http.Request) (err error) {
|
||||
var hash string
|
||||
hash, err = GetBodyHash(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
request.Header.Set(requestHeaderXContentSHA256, hash)
|
||||
return
|
||||
}
|
||||
|
||||
// drainBody reads all of b to memory and then returns two equivalent
|
||||
// ReadClosers yielding the same bytes.
|
||||
//
|
||||
// It returns an error if the initial slurp of all bytes fails. It does not attempt
|
||||
// to make the returned ReadClosers have identical error-matching behavior.
|
||||
func drainBody(b io.ReadCloser) (r1, r2 io.ReadCloser, err error) {
|
||||
if b == http.NoBody {
|
||||
// No copying needed. Preserve the magic sentinel meaning of NoBody.
|
||||
return http.NoBody, http.NoBody, nil
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
if _, err = buf.ReadFrom(b); err != nil {
|
||||
return nil, b, err
|
||||
}
|
||||
if err = b.Close(); err != nil {
|
||||
return nil, b, err
|
||||
}
|
||||
return ioutil.NopCloser(&buf), ioutil.NopCloser(bytes.NewReader(buf.Bytes())), nil
|
||||
}
|
||||
|
||||
func hashAndEncode(data []byte) string {
|
||||
hashedContent := sha256.Sum256(data)
|
||||
hash := base64.StdEncoding.EncodeToString(hashedContent[:])
|
||||
return hash
|
||||
}
|
||||
|
||||
// GetBodyHash creates a base64 string from the hash of body the request
|
||||
func GetBodyHash(request *http.Request) (hashString string, err error) {
|
||||
if request.Body == nil {
|
||||
request.ContentLength = 0
|
||||
request.Header.Set(requestHeaderContentLength, fmt.Sprintf("%v", request.ContentLength))
|
||||
return hashAndEncode([]byte("")), nil
|
||||
}
|
||||
|
||||
var data []byte
|
||||
bReader := request.Body
|
||||
bReader, request.Body, err = drainBody(request.Body)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can not read body of request while calculating body hash: %s", err.Error())
|
||||
}
|
||||
|
||||
data, err = ioutil.ReadAll(bReader)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("can not read body of request while calculating body hash: %s", err.Error())
|
||||
}
|
||||
|
||||
// Since the request can be coming from a binary body. Make an attempt to set the body length
|
||||
request.ContentLength = int64(len(data))
|
||||
request.Header.Set(requestHeaderContentLength, fmt.Sprintf("%v", request.ContentLength))
|
||||
|
||||
hashString = hashAndEncode(data)
|
||||
return
|
||||
}
|
||||
|
||||
func (signer ociRequestSigner) computeSignature(request *http.Request) (signature string, err error) {
|
||||
signingString := signer.getSigningString(request)
|
||||
hasher := sha256.New()
|
||||
hasher.Write([]byte(signingString))
|
||||
hashed := hasher.Sum(nil)
|
||||
|
||||
privateKey, err := signer.KeyProvider.PrivateRSAKey()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var unencodedSig []byte
|
||||
unencodedSig, e := rsa.SignPKCS1v15(rand.Reader, privateKey, crypto.SHA256, hashed)
|
||||
if e != nil {
|
||||
err = fmt.Errorf("can not compute signature while signing the request %s: ", e.Error())
|
||||
return
|
||||
}
|
||||
|
||||
signature = base64.StdEncoding.EncodeToString(unencodedSig)
|
||||
return
|
||||
}
|
||||
|
||||
// Sign signs the http request, by inspecting the necessary headers. Once signed
|
||||
// the request will have the proper 'Authorization' header set, otherwise
|
||||
// and error is returned
|
||||
func (signer ociRequestSigner) Sign(request *http.Request) (err error) {
|
||||
if signer.ShouldHashBody(request) {
|
||||
err = calculateHashOfBody(request)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var signature string
|
||||
if signature, err = signer.computeSignature(request); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
signingHeaders := strings.Join(signer.getSigningHeaders(request), " ")
|
||||
|
||||
var keyID string
|
||||
if keyID, err = signer.KeyProvider.KeyID(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
authValue := fmt.Sprintf("Signature version=\"%s\",headers=\"%s\",keyId=\"%s\",algorithm=\"rsa-sha256\",signature=\"%s\"",
|
||||
signerVersion, signingHeaders, keyID, signature)
|
||||
|
||||
request.Header.Set(requestHeaderAuthorization, authValue)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
//sdkLogger an interface for logging in the SDK
|
||||
type sdkLogger interface {
|
||||
//LogLevel returns the log level of sdkLogger
|
||||
LogLevel() int
|
||||
|
||||
//Log logs v with the provided format if the current log level is loglevel
|
||||
Log(logLevel int, format string, v ...interface{}) error
|
||||
}
|
||||
|
||||
//noLogging no logging messages
|
||||
const noLogging = 0
|
||||
|
||||
//infoLogging minimal logging messages
|
||||
const infoLogging = 1
|
||||
|
||||
//debugLogging some logging messages
|
||||
const debugLogging = 2
|
||||
|
||||
//verboseLogging all logging messages
|
||||
const verboseLogging = 3
|
||||
|
||||
//defaultSDKLogger the default implementation of the sdkLogger
|
||||
type defaultSDKLogger struct {
|
||||
currentLoggingLevel int
|
||||
verboseLogger *log.Logger
|
||||
debugLogger *log.Logger
|
||||
infoLogger *log.Logger
|
||||
nullLogger *log.Logger
|
||||
}
|
||||
|
||||
//defaultLogger is the defaultLogger in the SDK
|
||||
var defaultLogger sdkLogger
|
||||
var loggerLock sync.Mutex
|
||||
var file *os.File
|
||||
|
||||
//initializes the SDK defaultLogger as a defaultLogger
|
||||
func init() {
|
||||
l, _ := newSDKLogger()
|
||||
setSDKLogger(l)
|
||||
}
|
||||
|
||||
//setSDKLogger sets the logger used by the sdk
|
||||
func setSDKLogger(logger sdkLogger) {
|
||||
loggerLock.Lock()
|
||||
defaultLogger = logger
|
||||
loggerLock.Unlock()
|
||||
}
|
||||
|
||||
// newSDKLogger creates a defaultSDKLogger
|
||||
// Debug logging is turned on/off by the presence of the environment variable "OCI_GO_SDK_DEBUG"
|
||||
// The value of the "OCI_GO_SDK_DEBUG" environment variable controls the logging level.
|
||||
// "null" outputs no log messages
|
||||
// "i" or "info" outputs minimal log messages
|
||||
// "d" or "debug" outputs some logs messages
|
||||
// "v" or "verbose" outputs all logs messages, including body of requests
|
||||
func newSDKLogger() (defaultSDKLogger, error) {
|
||||
logger := defaultSDKLogger{}
|
||||
|
||||
logger.currentLoggingLevel = noLogging
|
||||
logger.verboseLogger = log.New(os.Stderr, "VERBOSE ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
|
||||
logger.debugLogger = log.New(os.Stderr, "DEBUG ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
|
||||
logger.infoLogger = log.New(os.Stderr, "INFO ", log.Ldate|log.Lmicroseconds|log.Lshortfile)
|
||||
logger.nullLogger = log.New(ioutil.Discard, "", log.Ldate|log.Lmicroseconds|log.Lshortfile)
|
||||
|
||||
configured, isLogEnabled := os.LookupEnv("OCI_GO_SDK_DEBUG")
|
||||
|
||||
// If env variable not present turn logging off
|
||||
if !isLogEnabled {
|
||||
logger.currentLoggingLevel = noLogging
|
||||
} else {
|
||||
logOutputModeConfig(logger)
|
||||
|
||||
switch strings.ToLower(configured) {
|
||||
case "null":
|
||||
logger.currentLoggingLevel = noLogging
|
||||
break
|
||||
case "i", "info":
|
||||
logger.currentLoggingLevel = infoLogging
|
||||
break
|
||||
case "d", "debug":
|
||||
logger.currentLoggingLevel = debugLogging
|
||||
break
|
||||
//1 here for backwards compatibility
|
||||
case "v", "verbose", "1":
|
||||
logger.currentLoggingLevel = verboseLogging
|
||||
break
|
||||
default:
|
||||
logger.currentLoggingLevel = infoLogging
|
||||
}
|
||||
logger.infoLogger.Println("logger level set to: ", logger.currentLoggingLevel)
|
||||
}
|
||||
|
||||
return logger, nil
|
||||
}
|
||||
|
||||
func (l defaultSDKLogger) getLoggerForLevel(logLevel int) *log.Logger {
|
||||
if logLevel > l.currentLoggingLevel {
|
||||
return l.nullLogger
|
||||
}
|
||||
|
||||
switch logLevel {
|
||||
case noLogging:
|
||||
return l.nullLogger
|
||||
case infoLogging:
|
||||
return l.infoLogger
|
||||
case debugLogging:
|
||||
return l.debugLogger
|
||||
case verboseLogging:
|
||||
return l.verboseLogger
|
||||
default:
|
||||
return l.nullLogger
|
||||
}
|
||||
}
|
||||
|
||||
// Set SDK Log output mode
|
||||
// Output mode is switched based on environment variable "OCI_GO_SDK_LOG_OUPUT_MODE"
|
||||
// "file" outputs log to a specific file
|
||||
// "combine" outputs log to both stderr and specific file
|
||||
// other unsupported value outputs log to stderr
|
||||
// output file can be set via environment variable "OCI_GO_SDK_LOG_FILE"
|
||||
// if this environment variable is not set, a default log file will be created under project root path
|
||||
func logOutputModeConfig(logger defaultSDKLogger) {
|
||||
logMode, isLogOutputModeEnabled := os.LookupEnv("OCI_GO_SDK_LOG_OUTPUT_MODE")
|
||||
if !isLogOutputModeEnabled {
|
||||
return
|
||||
}
|
||||
fileName, isLogFileNameProvided := os.LookupEnv("OCI_GO_SDK_LOG_FILE")
|
||||
if !isLogFileNameProvided {
|
||||
fileName = fmt.Sprintf("logging_%v%s", time.Now().Unix(), ".log")
|
||||
}
|
||||
|
||||
switch strings.ToLower(logMode) {
|
||||
case "file", "f":
|
||||
file = openLogOutputFile(logger, fileName)
|
||||
logger.infoLogger.SetOutput(file)
|
||||
logger.debugLogger.SetOutput(file)
|
||||
logger.verboseLogger.SetOutput(file)
|
||||
break
|
||||
case "combine", "c":
|
||||
file = openLogOutputFile(logger, fileName)
|
||||
wrt := io.MultiWriter(os.Stderr, file)
|
||||
|
||||
logger.infoLogger.SetOutput(wrt)
|
||||
logger.debugLogger.SetOutput(wrt)
|
||||
logger.verboseLogger.SetOutput(wrt)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func openLogOutputFile(logger defaultSDKLogger, fileName string) *os.File {
|
||||
file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||
if err != nil {
|
||||
logger.verboseLogger.Fatal(err)
|
||||
}
|
||||
return file
|
||||
}
|
||||
|
||||
//CloseLogFile close the logging file and return error
|
||||
func CloseLogFile() error {
|
||||
return file.Close()
|
||||
}
|
||||
|
||||
//LogLevel returns the current debug level
|
||||
func (l defaultSDKLogger) LogLevel() int {
|
||||
return l.currentLoggingLevel
|
||||
}
|
||||
|
||||
func (l defaultSDKLogger) Log(logLevel int, format string, v ...interface{}) error {
|
||||
logger := l.getLoggerForLevel(logLevel)
|
||||
logger.Output(4, fmt.Sprintf(format, v...))
|
||||
return nil
|
||||
}
|
||||
|
||||
//Logln logs v appending a new line at the end
|
||||
//Deprecated
|
||||
func Logln(v ...interface{}) {
|
||||
defaultLogger.Log(infoLogging, "%v\n", v...)
|
||||
}
|
||||
|
||||
// Logf logs v with the provided format
|
||||
func Logf(format string, v ...interface{}) {
|
||||
defaultLogger.Log(infoLogging, format, v...)
|
||||
}
|
||||
|
||||
// Debugf logs v with the provided format if debug mode is set
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
defaultLogger.Log(debugLogging, format, v...)
|
||||
}
|
||||
|
||||
// Debug logs v if debug mode is set
|
||||
func Debug(v ...interface{}) {
|
||||
m := fmt.Sprint(v...)
|
||||
defaultLogger.Log(debugLogging, "%s", m)
|
||||
}
|
||||
|
||||
// Debugln logs v appending a new line if debug mode is set
|
||||
func Debugln(v ...interface{}) {
|
||||
m := fmt.Sprint(v...)
|
||||
defaultLogger.Log(debugLogging, "%s\n", m)
|
||||
}
|
||||
|
||||
// IfDebug executes closure if debug is enabled
|
||||
func IfDebug(fn func()) {
|
||||
if defaultLogger.LogLevel() >= debugLogging {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
||||
// IfInfo executes closure if info is enabled
|
||||
func IfInfo(fn func()) {
|
||||
if defaultLogger.LogLevel() >= infoLogging {
|
||||
fn()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"math/rand"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// UnlimitedNumAttemptsValue is the value for indicating unlimited attempts for reaching success
|
||||
UnlimitedNumAttemptsValue = uint(0)
|
||||
|
||||
// number of characters contained in the generated retry token
|
||||
generatedRetryTokenLength = 32
|
||||
)
|
||||
|
||||
// OCIRetryableRequest represents a request that can be reissued according to the specified policy.
|
||||
type OCIRetryableRequest interface {
|
||||
// Any retryable request must implement the OCIRequest interface
|
||||
OCIRequest
|
||||
|
||||
// Each operation should implement this method, if has binary body, return OCIReadSeekCloser and true, otherwise return nil, false
|
||||
BinaryRequestBody() (*OCIReadSeekCloser, bool)
|
||||
|
||||
// Each operation specifies default retry behavior. By passing no arguments to this method, the default retry
|
||||
// behavior, as determined on a per-operation-basis, will be honored. Variadic retry policy option arguments
|
||||
// passed to this method will override the default behavior.
|
||||
RetryPolicy() *RetryPolicy
|
||||
}
|
||||
|
||||
// OCIOperationResponse represents the output of an OCIOperation, with additional context of error message
|
||||
// and operation attempt number.
|
||||
type OCIOperationResponse struct {
|
||||
// Response from OCI Operation
|
||||
Response OCIResponse
|
||||
|
||||
// Error from OCI Operation
|
||||
Error error
|
||||
|
||||
// Operation Attempt Number (one-based)
|
||||
AttemptNumber uint
|
||||
}
|
||||
|
||||
// NewOCIOperationResponse assembles an OCI Operation Response object.
|
||||
func NewOCIOperationResponse(response OCIResponse, err error, attempt uint) OCIOperationResponse {
|
||||
return OCIOperationResponse{
|
||||
Response: response,
|
||||
Error: err,
|
||||
AttemptNumber: attempt,
|
||||
}
|
||||
}
|
||||
|
||||
// RetryPolicy is the class that holds all relevant information for retrying operations.
|
||||
type RetryPolicy struct {
|
||||
// MaximumNumberAttempts is the maximum number of times to retry a request. Zero indicates an unlimited
|
||||
// number of attempts.
|
||||
MaximumNumberAttempts uint
|
||||
|
||||
// ShouldRetryOperation inspects the http response, error, and operation attempt number, and
|
||||
// - returns true if we should retry the operation
|
||||
// - returns false otherwise
|
||||
ShouldRetryOperation func(OCIOperationResponse) bool
|
||||
|
||||
// GetNextDuration computes the duration to pause between operation retries.
|
||||
NextDuration func(OCIOperationResponse) time.Duration
|
||||
}
|
||||
|
||||
// NoRetryPolicy is a helper method that assembles and returns a return policy that indicates an operation should
|
||||
// never be retried (the operation is performed exactly once).
|
||||
func NoRetryPolicy() RetryPolicy {
|
||||
dontRetryOperation := func(OCIOperationResponse) bool { return false }
|
||||
zeroNextDuration := func(OCIOperationResponse) time.Duration { return 0 * time.Second }
|
||||
return NewRetryPolicy(uint(1), dontRetryOperation, zeroNextDuration)
|
||||
}
|
||||
|
||||
// DefaultRetryPolicy is a helper method that assembles and returns a return policy that is defined to be a default one
|
||||
// The default retry policy will retry on (409, IncorrectState), (429, TooManyRequests) and any 5XX errors except (501, MethodNotImplemented)
|
||||
// The default retry behavior is using exponential backoff with jitter, the maximum wait time is 30s
|
||||
func DefaultRetryPolicy() RetryPolicy {
|
||||
defaultRetryPolicy := func(r OCIOperationResponse) bool {
|
||||
type HTTPStatus struct {
|
||||
code int
|
||||
message string
|
||||
}
|
||||
defaultRetryStatusCodeMap := map[HTTPStatus]bool{
|
||||
{409, "IncorrectState"}: true,
|
||||
{429, "TooManyRequests"}: true,
|
||||
|
||||
{501, "MethodNotImplemented"}: false,
|
||||
}
|
||||
|
||||
if r.Error == nil && 199 < r.Response.HTTPResponse().StatusCode && r.Response.HTTPResponse().StatusCode < 300 {
|
||||
return false
|
||||
}
|
||||
if IsNetworkError(r.Error) {
|
||||
return true
|
||||
}
|
||||
if err, ok := IsServiceError(r.Error); ok {
|
||||
if shouldRetry, ok := defaultRetryStatusCodeMap[HTTPStatus{err.GetHTTPStatusCode(), err.GetCode()}]; ok {
|
||||
return shouldRetry
|
||||
}
|
||||
return 500 <= r.Response.HTTPResponse().StatusCode && r.Response.HTTPResponse().StatusCode < 600
|
||||
}
|
||||
return false
|
||||
}
|
||||
maxSleepBetween := 30.0
|
||||
exponentialBackoffWithJitter := func(r OCIOperationResponse) time.Duration {
|
||||
sleepTime := math.Pow(float64(2), float64(r.AttemptNumber-1))
|
||||
if sleepTime < maxSleepBetween {
|
||||
return time.Duration(sleepTime+rand.Float64()) * time.Second
|
||||
}
|
||||
return time.Duration(maxSleepBetween+rand.Float64()) * time.Second
|
||||
}
|
||||
return NewRetryPolicy(uint(8), defaultRetryPolicy, exponentialBackoffWithJitter)
|
||||
}
|
||||
|
||||
// NewRetryPolicy is a helper method for assembling a Retry Policy object.
|
||||
func NewRetryPolicy(attempts uint, retryOperation func(OCIOperationResponse) bool, nextDuration func(OCIOperationResponse) time.Duration) RetryPolicy {
|
||||
return RetryPolicy{
|
||||
MaximumNumberAttempts: attempts,
|
||||
ShouldRetryOperation: retryOperation,
|
||||
NextDuration: nextDuration,
|
||||
}
|
||||
}
|
||||
|
||||
// shouldContinueIssuingRequests returns true if we should continue retrying a request, based on the current attempt
|
||||
// number and the maximum number of attempts specified, or false otherwise.
|
||||
func shouldContinueIssuingRequests(current, maximum uint) bool {
|
||||
return maximum == UnlimitedNumAttemptsValue || current <= maximum
|
||||
}
|
||||
|
||||
// RetryToken generates a retry token that must be included on any request passed to the Retry method.
|
||||
func RetryToken() string {
|
||||
alphanumericChars := []rune("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||||
retryToken := make([]rune, generatedRetryTokenLength)
|
||||
for i := range retryToken {
|
||||
retryToken[i] = alphanumericChars[rand.Intn(len(alphanumericChars))]
|
||||
}
|
||||
return string(retryToken)
|
||||
}
|
||||
|
||||
// Retry is a package-level operation that executes the retryable request using the specified operation and retry policy.
|
||||
func Retry(ctx context.Context, request OCIRetryableRequest, operation OCIOperation, policy RetryPolicy) (OCIResponse, error) {
|
||||
|
||||
type retrierResult struct {
|
||||
response OCIResponse
|
||||
err error
|
||||
}
|
||||
|
||||
var response OCIResponse
|
||||
var err error
|
||||
retrierChannel := make(chan retrierResult)
|
||||
|
||||
go func() {
|
||||
|
||||
// Deal with panics more graciously
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
stackBuffer := make([]byte, 1024)
|
||||
bytesWritten := runtime.Stack(stackBuffer, false)
|
||||
stack := string(stackBuffer[:bytesWritten])
|
||||
retrierChannel <- retrierResult{nil, fmt.Errorf("panicked while retrying operation. Panic was: %s\nStack: %s", r, stack)}
|
||||
}
|
||||
}()
|
||||
|
||||
// if request body is binary request body and seekable, save the current position
|
||||
var curPos int64 = 0
|
||||
isSeekable := false
|
||||
rsc, isBinaryRequest := request.BinaryRequestBody()
|
||||
if rsc != nil {
|
||||
defer rsc.rc.Close()
|
||||
}
|
||||
if policy.MaximumNumberAttempts != uint(1) {
|
||||
if rsc.Seekable() {
|
||||
isSeekable = true
|
||||
curPos, _ = rsc.Seek(0, io.SeekCurrent)
|
||||
}
|
||||
}
|
||||
|
||||
// use a one-based counter because it's easier to think about operation retry in terms of attempt numbering
|
||||
for currentOperationAttempt := uint(1); shouldContinueIssuingRequests(currentOperationAttempt, policy.MaximumNumberAttempts); currentOperationAttempt++ {
|
||||
Debugln(fmt.Sprintf("operation attempt #%v", currentOperationAttempt))
|
||||
// rewind body once needed
|
||||
if isSeekable {
|
||||
rsc = NewOCIReadSeekCloser(rsc.rc)
|
||||
rsc.Seek(curPos, io.SeekStart)
|
||||
}
|
||||
response, err = operation(ctx, request, rsc)
|
||||
|
||||
operationResponse := NewOCIOperationResponse(response, err, currentOperationAttempt)
|
||||
|
||||
if !policy.ShouldRetryOperation(operationResponse) {
|
||||
// we should NOT retry operation based on response and/or error => return
|
||||
retrierChannel <- retrierResult{response, err}
|
||||
return
|
||||
}
|
||||
|
||||
// if the request body type is stream, requested retry but doesn't resettable, throw error and stop retrying
|
||||
if isBinaryRequest && !isSeekable {
|
||||
retrierChannel <- retrierResult{response, NonSeekableRequestRetryFailure{err}}
|
||||
return
|
||||
}
|
||||
|
||||
duration := policy.NextDuration(operationResponse)
|
||||
//The following condition is kept for backwards compatibility reasons
|
||||
if deadline, ok := ctx.Deadline(); ok && time.Now().Add(duration).After(deadline) {
|
||||
// we want to retry the operation, but the policy is telling us to wait for a duration that exceeds
|
||||
// the specified overall deadline for the operation => instead of waiting for however long that
|
||||
// time period is and then aborting, abort now and save the cycles
|
||||
retrierChannel <- retrierResult{response, DeadlineExceededByBackoff}
|
||||
return
|
||||
}
|
||||
Debugln(fmt.Sprintf("waiting %v before retrying operation", duration))
|
||||
// sleep before retrying the operation
|
||||
<-time.After(duration)
|
||||
}
|
||||
|
||||
retrierChannel <- retrierResult{response, err}
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return response, ctx.Err()
|
||||
case result := <-retrierChannel:
|
||||
return result.response, result.err
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2016, 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated by go generate; DO NOT EDIT
|
||||
|
||||
package common
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const (
|
||||
major = "43"
|
||||
minor = "1"
|
||||
patch = "0"
|
||||
tag = ""
|
||||
)
|
||||
|
||||
var once sync.Once
|
||||
var version string
|
||||
|
||||
// Version returns semantic version of the sdk
|
||||
func Version() string {
|
||||
once.Do(func() {
|
||||
ver := fmt.Sprintf("%s.%s.%s", major, minor, patch)
|
||||
verBuilder := bytes.NewBufferString(ver)
|
||||
if tag != "" && tag != "-" {
|
||||
_, err := verBuilder.WriteString(tag)
|
||||
if err != nil {
|
||||
verBuilder = bytes.NewBufferString(ver)
|
||||
}
|
||||
}
|
||||
version = verBuilder.String()
|
||||
})
|
||||
return version
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// AddOnOptions The properties that define options for supported add-ons.
|
||||
type AddOnOptions struct {
|
||||
|
||||
// Whether or not to enable the Kubernetes Dashboard add-on.
|
||||
IsKubernetesDashboardEnabled *bool `mandatory:"false" json:"isKubernetesDashboardEnabled"`
|
||||
|
||||
// Whether or not to enable the Tiller add-on.
|
||||
IsTillerEnabled *bool `mandatory:"false" json:"isTillerEnabled"`
|
||||
}
|
||||
|
||||
func (m AddOnOptions) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// AdmissionControllerOptions The properties that define supported admission controllers.
|
||||
type AdmissionControllerOptions struct {
|
||||
|
||||
// Whether or not to enable the Pod Security Policy admission controller.
|
||||
IsPodSecurityPolicyEnabled *bool `mandatory:"false" json:"isPodSecurityPolicyEnabled"`
|
||||
}
|
||||
|
||||
func (m AdmissionControllerOptions) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// Cluster A Kubernetes cluster. Avoid entering confidential information.
|
||||
type Cluster struct {
|
||||
|
||||
// The OCID of the cluster.
|
||||
Id *string `mandatory:"false" json:"id"`
|
||||
|
||||
// The name of the cluster.
|
||||
Name *string `mandatory:"false" json:"name"`
|
||||
|
||||
// The OCID of the compartment in which the cluster exists.
|
||||
CompartmentId *string `mandatory:"false" json:"compartmentId"`
|
||||
|
||||
// The network configuration for access to the Cluster control plane.
|
||||
EndpointConfig *ClusterEndpointConfig `mandatory:"false" json:"endpointConfig"`
|
||||
|
||||
// The OCID of the virtual cloud network (VCN) in which the cluster exists.
|
||||
VcnId *string `mandatory:"false" json:"vcnId"`
|
||||
|
||||
// The version of Kubernetes running on the cluster masters.
|
||||
KubernetesVersion *string `mandatory:"false" json:"kubernetesVersion"`
|
||||
|
||||
// The OCID of the KMS key to be used as the master encryption key for Kubernetes secret encryption.
|
||||
KmsKeyId *string `mandatory:"false" json:"kmsKeyId"`
|
||||
|
||||
// Optional attributes for the cluster.
|
||||
Options *ClusterCreateOptions `mandatory:"false" json:"options"`
|
||||
|
||||
// Metadata about the cluster.
|
||||
Metadata *ClusterMetadata `mandatory:"false" json:"metadata"`
|
||||
|
||||
// The state of the cluster masters.
|
||||
LifecycleState ClusterLifecycleStateEnum `mandatory:"false" json:"lifecycleState,omitempty"`
|
||||
|
||||
// Details about the state of the cluster masters.
|
||||
LifecycleDetails *string `mandatory:"false" json:"lifecycleDetails"`
|
||||
|
||||
// Endpoints served up by the cluster masters.
|
||||
Endpoints *ClusterEndpoints `mandatory:"false" json:"endpoints"`
|
||||
|
||||
// Available Kubernetes versions to which the clusters masters may be upgraded.
|
||||
AvailableKubernetesUpgrades []string `mandatory:"false" json:"availableKubernetesUpgrades"`
|
||||
|
||||
// The image verification policy for signature validation.
|
||||
ImagePolicyConfig *ImagePolicyConfig `mandatory:"false" json:"imagePolicyConfig"`
|
||||
}
|
||||
|
||||
func (m Cluster) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterCreateOptions The properties that define extra options for a cluster.
|
||||
type ClusterCreateOptions struct {
|
||||
|
||||
// The OCIDs of the subnets used for Kubernetes services load balancers.
|
||||
ServiceLbSubnetIds []string `mandatory:"false" json:"serviceLbSubnetIds"`
|
||||
|
||||
// Network configuration for Kubernetes.
|
||||
KubernetesNetworkConfig *KubernetesNetworkConfig `mandatory:"false" json:"kubernetesNetworkConfig"`
|
||||
|
||||
// Configurable cluster add-ons
|
||||
AddOns *AddOnOptions `mandatory:"false" json:"addOns"`
|
||||
|
||||
// Configurable cluster admission controllers
|
||||
AdmissionControllerOptions *AdmissionControllerOptions `mandatory:"false" json:"admissionControllerOptions"`
|
||||
}
|
||||
|
||||
func (m ClusterCreateOptions) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterEndpointConfig The properties that define the network configuration for the Cluster endpoint.
|
||||
type ClusterEndpointConfig struct {
|
||||
|
||||
// The OCID of the regional subnet in which to place the Cluster endpoint.
|
||||
SubnetId *string `mandatory:"false" json:"subnetId"`
|
||||
|
||||
// A list of the OCIDs of the network security groups (NSGs) to apply to the cluster endpoint. For more information about NSGs, see NetworkSecurityGroup.
|
||||
NsgIds []string `mandatory:"false" json:"nsgIds"`
|
||||
|
||||
// Whether the cluster should be assigned a public IP address. Defaults to false. If set to true on a private subnet, the cluster provisioning will fail.
|
||||
IsPublicIpEnabled *bool `mandatory:"false" json:"isPublicIpEnabled"`
|
||||
}
|
||||
|
||||
func (m ClusterEndpointConfig) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterEndpoints The properties that define endpoints for a cluster.
|
||||
type ClusterEndpoints struct {
|
||||
|
||||
// The non-native networking Kubernetes API server endpoint.
|
||||
Kubernetes *string `mandatory:"false" json:"kubernetes"`
|
||||
|
||||
// The public native networking Kubernetes API server endpoint, if one was requested.
|
||||
PublicEndpoint *string `mandatory:"false" json:"publicEndpoint"`
|
||||
|
||||
// The private native networking Kubernetes API server endpoint.
|
||||
PrivateEndpoint *string `mandatory:"false" json:"privateEndpoint"`
|
||||
}
|
||||
|
||||
func (m ClusterEndpoints) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
// ClusterLifecycleStateEnum Enum with underlying type: string
|
||||
type ClusterLifecycleStateEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ClusterLifecycleStateEnum
|
||||
const (
|
||||
ClusterLifecycleStateCreating ClusterLifecycleStateEnum = "CREATING"
|
||||
ClusterLifecycleStateActive ClusterLifecycleStateEnum = "ACTIVE"
|
||||
ClusterLifecycleStateFailed ClusterLifecycleStateEnum = "FAILED"
|
||||
ClusterLifecycleStateDeleting ClusterLifecycleStateEnum = "DELETING"
|
||||
ClusterLifecycleStateDeleted ClusterLifecycleStateEnum = "DELETED"
|
||||
ClusterLifecycleStateUpdating ClusterLifecycleStateEnum = "UPDATING"
|
||||
)
|
||||
|
||||
var mappingClusterLifecycleState = map[string]ClusterLifecycleStateEnum{
|
||||
"CREATING": ClusterLifecycleStateCreating,
|
||||
"ACTIVE": ClusterLifecycleStateActive,
|
||||
"FAILED": ClusterLifecycleStateFailed,
|
||||
"DELETING": ClusterLifecycleStateDeleting,
|
||||
"DELETED": ClusterLifecycleStateDeleted,
|
||||
"UPDATING": ClusterLifecycleStateUpdating,
|
||||
}
|
||||
|
||||
// GetClusterLifecycleStateEnumValues Enumerates the set of values for ClusterLifecycleStateEnum
|
||||
func GetClusterLifecycleStateEnumValues() []ClusterLifecycleStateEnum {
|
||||
values := make([]ClusterLifecycleStateEnum, 0)
|
||||
for _, v := range mappingClusterLifecycleState {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterMetadata The properties that define meta data for a cluster.
|
||||
type ClusterMetadata struct {
|
||||
|
||||
// The time the cluster was created.
|
||||
TimeCreated *common.SDKTime `mandatory:"false" json:"timeCreated"`
|
||||
|
||||
// The user who created the cluster.
|
||||
CreatedByUserId *string `mandatory:"false" json:"createdByUserId"`
|
||||
|
||||
// The OCID of the work request which created the cluster.
|
||||
CreatedByWorkRequestId *string `mandatory:"false" json:"createdByWorkRequestId"`
|
||||
|
||||
// The time the cluster was deleted.
|
||||
TimeDeleted *common.SDKTime `mandatory:"false" json:"timeDeleted"`
|
||||
|
||||
// The user who deleted the cluster.
|
||||
DeletedByUserId *string `mandatory:"false" json:"deletedByUserId"`
|
||||
|
||||
// The OCID of the work request which deleted the cluster.
|
||||
DeletedByWorkRequestId *string `mandatory:"false" json:"deletedByWorkRequestId"`
|
||||
|
||||
// The time the cluster was updated.
|
||||
TimeUpdated *common.SDKTime `mandatory:"false" json:"timeUpdated"`
|
||||
|
||||
// The user who updated the cluster.
|
||||
UpdatedByUserId *string `mandatory:"false" json:"updatedByUserId"`
|
||||
|
||||
// The OCID of the work request which updated the cluster.
|
||||
UpdatedByWorkRequestId *string `mandatory:"false" json:"updatedByWorkRequestId"`
|
||||
}
|
||||
|
||||
func (m ClusterMetadata) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterMigrateToNativeVcnDetails The properties that define a request to migrate a cluster to Native VCN.
|
||||
type ClusterMigrateToNativeVcnDetails struct {
|
||||
|
||||
// The network configuration for access to the Cluster control plane.
|
||||
EndpointConfig *ClusterEndpointConfig `mandatory:"true" json:"endpointConfig"`
|
||||
|
||||
// The optional override of the non-native endpoint decommission time after migration is complete. Defaults to 30 days.
|
||||
DecommissionDelayDuration *string `mandatory:"false" json:"decommissionDelayDuration"`
|
||||
}
|
||||
|
||||
func (m ClusterMigrateToNativeVcnDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ClusterMigrateToNativeVcnRequest wrapper for the ClusterMigrateToNativeVcn operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/ClusterMigrateToNativeVcn.go.html to see an example of how to use ClusterMigrateToNativeVcnRequest.
|
||||
type ClusterMigrateToNativeVcnRequest struct {
|
||||
|
||||
// The OCID of the cluster.
|
||||
ClusterId *string `mandatory:"true" contributesTo:"path" name:"clusterId"`
|
||||
|
||||
// The details for the cluster's migration to native VCN.
|
||||
ClusterMigrateToNativeVcnDetails `contributesTo:"body"`
|
||||
|
||||
// For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match`
|
||||
// parameter to the value of the etag from a previous GET or POST response for that resource. The resource
|
||||
// will be updated or deleted only if the etag you provide matches the resource's current etag value.
|
||||
IfMatch *string `mandatory:"false" contributesTo:"header" name:"if-match"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request ClusterMigrateToNativeVcnRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request ClusterMigrateToNativeVcnRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request ClusterMigrateToNativeVcnRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request ClusterMigrateToNativeVcnRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// ClusterMigrateToNativeVcnResponse wrapper for the ClusterMigrateToNativeVcn operation
|
||||
type ClusterMigrateToNativeVcnResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The OCID of the work request handling the operation.
|
||||
OpcWorkRequestId *string `presentIn:"header" name:"opc-work-request-id"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response ClusterMigrateToNativeVcnResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response ClusterMigrateToNativeVcnResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterMigrateToNativeVcnStatus Information regarding a cluster's move to Native VCN.
|
||||
type ClusterMigrateToNativeVcnStatus struct {
|
||||
|
||||
// The current migration status of the cluster.
|
||||
State ClusterMigrateToNativeVcnStatusStateEnum `mandatory:"true" json:"state"`
|
||||
|
||||
// The date and time the non-native VCN is due to be decommissioned.
|
||||
TimeDecommissionScheduled *common.SDKTime `mandatory:"false" json:"timeDecommissionScheduled"`
|
||||
}
|
||||
|
||||
func (m ClusterMigrateToNativeVcnStatus) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// ClusterMigrateToNativeVcnStatusStateEnum Enum with underlying type: string
|
||||
type ClusterMigrateToNativeVcnStatusStateEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ClusterMigrateToNativeVcnStatusStateEnum
|
||||
const (
|
||||
ClusterMigrateToNativeVcnStatusStateNotStarted ClusterMigrateToNativeVcnStatusStateEnum = "NOT_STARTED"
|
||||
ClusterMigrateToNativeVcnStatusStateRequested ClusterMigrateToNativeVcnStatusStateEnum = "REQUESTED"
|
||||
ClusterMigrateToNativeVcnStatusStateInProgress ClusterMigrateToNativeVcnStatusStateEnum = "IN_PROGRESS"
|
||||
ClusterMigrateToNativeVcnStatusStatePendingDecommission ClusterMigrateToNativeVcnStatusStateEnum = "PENDING_DECOMMISSION"
|
||||
ClusterMigrateToNativeVcnStatusStateCompleted ClusterMigrateToNativeVcnStatusStateEnum = "COMPLETED"
|
||||
)
|
||||
|
||||
var mappingClusterMigrateToNativeVcnStatusState = map[string]ClusterMigrateToNativeVcnStatusStateEnum{
|
||||
"NOT_STARTED": ClusterMigrateToNativeVcnStatusStateNotStarted,
|
||||
"REQUESTED": ClusterMigrateToNativeVcnStatusStateRequested,
|
||||
"IN_PROGRESS": ClusterMigrateToNativeVcnStatusStateInProgress,
|
||||
"PENDING_DECOMMISSION": ClusterMigrateToNativeVcnStatusStatePendingDecommission,
|
||||
"COMPLETED": ClusterMigrateToNativeVcnStatusStateCompleted,
|
||||
}
|
||||
|
||||
// GetClusterMigrateToNativeVcnStatusStateEnumValues Enumerates the set of values for ClusterMigrateToNativeVcnStatusStateEnum
|
||||
func GetClusterMigrateToNativeVcnStatusStateEnumValues() []ClusterMigrateToNativeVcnStatusStateEnum {
|
||||
values := make([]ClusterMigrateToNativeVcnStatusStateEnum, 0)
|
||||
for _, v := range mappingClusterMigrateToNativeVcnStatusState {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterOptions Options for creating or updating clusters.
|
||||
type ClusterOptions struct {
|
||||
|
||||
// Available Kubernetes versions.
|
||||
KubernetesVersions []string `mandatory:"false" json:"kubernetesVersions"`
|
||||
}
|
||||
|
||||
func (m ClusterOptions) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ClusterSummary The properties that define a cluster summary.
|
||||
type ClusterSummary struct {
|
||||
|
||||
// The OCID of the cluster.
|
||||
Id *string `mandatory:"false" json:"id"`
|
||||
|
||||
// The name of the cluster.
|
||||
Name *string `mandatory:"false" json:"name"`
|
||||
|
||||
// The OCID of the compartment in which the cluster exists.
|
||||
CompartmentId *string `mandatory:"false" json:"compartmentId"`
|
||||
|
||||
// The network configuration for access to the Cluster control plane.
|
||||
EndpointConfig *ClusterEndpointConfig `mandatory:"false" json:"endpointConfig"`
|
||||
|
||||
// The OCID of the virtual cloud network (VCN) in which the cluster exists
|
||||
VcnId *string `mandatory:"false" json:"vcnId"`
|
||||
|
||||
// The version of Kubernetes running on the cluster masters.
|
||||
KubernetesVersion *string `mandatory:"false" json:"kubernetesVersion"`
|
||||
|
||||
// Optional attributes for the cluster.
|
||||
Options *ClusterCreateOptions `mandatory:"false" json:"options"`
|
||||
|
||||
// Metadata about the cluster.
|
||||
Metadata *ClusterMetadata `mandatory:"false" json:"metadata"`
|
||||
|
||||
// The state of the cluster masters.
|
||||
LifecycleState ClusterLifecycleStateEnum `mandatory:"false" json:"lifecycleState,omitempty"`
|
||||
|
||||
// Details about the state of the cluster masters.
|
||||
LifecycleDetails *string `mandatory:"false" json:"lifecycleDetails"`
|
||||
|
||||
// Endpoints served up by the cluster masters.
|
||||
Endpoints *ClusterEndpoints `mandatory:"false" json:"endpoints"`
|
||||
|
||||
// Available Kubernetes versions to which the clusters masters may be upgraded.
|
||||
AvailableKubernetesUpgrades []string `mandatory:"false" json:"availableKubernetesUpgrades"`
|
||||
|
||||
// The image verification policy for signature validation.
|
||||
ImagePolicyConfig *ImagePolicyConfig `mandatory:"false" json:"imagePolicyConfig"`
|
||||
}
|
||||
|
||||
func (m ClusterSummary) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// ClusterSummaryLifecycleStateEnum is an alias to type: ClusterLifecycleStateEnum
|
||||
// Consider using ClusterLifecycleStateEnum instead
|
||||
// Deprecated
|
||||
type ClusterSummaryLifecycleStateEnum = ClusterLifecycleStateEnum
|
||||
|
||||
// Set of constants representing the allowable values for ClusterLifecycleStateEnum
|
||||
// Deprecated
|
||||
const (
|
||||
ClusterSummaryLifecycleStateCreating ClusterLifecycleStateEnum = "CREATING"
|
||||
ClusterSummaryLifecycleStateActive ClusterLifecycleStateEnum = "ACTIVE"
|
||||
ClusterSummaryLifecycleStateFailed ClusterLifecycleStateEnum = "FAILED"
|
||||
ClusterSummaryLifecycleStateDeleting ClusterLifecycleStateEnum = "DELETING"
|
||||
ClusterSummaryLifecycleStateDeleted ClusterLifecycleStateEnum = "DELETED"
|
||||
ClusterSummaryLifecycleStateUpdating ClusterLifecycleStateEnum = "UPDATING"
|
||||
)
|
||||
|
||||
// GetClusterSummaryLifecycleStateEnumValues Enumerates the set of values for ClusterLifecycleStateEnum
|
||||
// Consider using GetClusterLifecycleStateEnumValue
|
||||
// Deprecated
|
||||
var GetClusterSummaryLifecycleStateEnumValues = GetClusterLifecycleStateEnumValues
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,51 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// CreateClusterDetails The properties that define a request to create a cluster.
|
||||
type CreateClusterDetails struct {
|
||||
|
||||
// The name of the cluster. Avoid entering confidential information.
|
||||
Name *string `mandatory:"true" json:"name"`
|
||||
|
||||
// The OCID of the compartment in which to create the cluster.
|
||||
CompartmentId *string `mandatory:"true" json:"compartmentId"`
|
||||
|
||||
// The OCID of the virtual cloud network (VCN) in which to create the cluster.
|
||||
VcnId *string `mandatory:"true" json:"vcnId"`
|
||||
|
||||
// The version of Kubernetes to install into the cluster masters.
|
||||
KubernetesVersion *string `mandatory:"true" json:"kubernetesVersion"`
|
||||
|
||||
// The network configuration for access to the Cluster control plane.
|
||||
EndpointConfig *CreateClusterEndpointConfigDetails `mandatory:"false" json:"endpointConfig"`
|
||||
|
||||
// The OCID of the KMS key to be used as the master encryption key for Kubernetes secret encryption.
|
||||
// When used, `kubernetesVersion` must be at least `v1.13.0`.
|
||||
KmsKeyId *string `mandatory:"false" json:"kmsKeyId"`
|
||||
|
||||
// Optional attributes for the cluster.
|
||||
Options *ClusterCreateOptions `mandatory:"false" json:"options"`
|
||||
|
||||
// The image verification policy for signature validation. Once a policy is created and enabled with
|
||||
// one or more kms keys, the policy will ensure all images deployed has been signed with the key(s)
|
||||
// attached to the policy.
|
||||
ImagePolicyConfig *CreateImagePolicyConfigDetails `mandatory:"false" json:"imagePolicyConfig"`
|
||||
}
|
||||
|
||||
func (m CreateClusterDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// CreateClusterEndpointConfigDetails The properties that define the network configuration for the Cluster endpoint.
|
||||
type CreateClusterEndpointConfigDetails struct {
|
||||
|
||||
// The OCID of the regional subnet in which to place the Cluster endpoint.
|
||||
SubnetId *string `mandatory:"false" json:"subnetId"`
|
||||
|
||||
// A list of the OCIDs of the network security groups (NSGs) to apply to the cluster endpoint. For more information about NSGs, see NetworkSecurityGroup.
|
||||
NsgIds []string `mandatory:"false" json:"nsgIds"`
|
||||
|
||||
// Whether the cluster should be assigned a public IP address. Defaults to false. If set to true on a private subnet, the cluster provisioning will fail.
|
||||
IsPublicIpEnabled *bool `mandatory:"false" json:"isPublicIpEnabled"`
|
||||
}
|
||||
|
||||
func (m CreateClusterEndpointConfigDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// CreateClusterKubeconfigContentDetails The properties that define a request to create a cluster kubeconfig.
|
||||
type CreateClusterKubeconfigContentDetails struct {
|
||||
|
||||
// The version of the kubeconfig token. Supported value 2.0.0
|
||||
TokenVersion *string `mandatory:"false" json:"tokenVersion"`
|
||||
|
||||
// Deprecated. This field is no longer used.
|
||||
Expiration *int `mandatory:"false" json:"expiration"`
|
||||
|
||||
// The endpoint to target. A cluster may have multiple endpoints exposed but the kubeconfig can only target one at a time.
|
||||
Endpoint CreateClusterKubeconfigContentDetailsEndpointEnum `mandatory:"false" json:"endpoint,omitempty"`
|
||||
}
|
||||
|
||||
func (m CreateClusterKubeconfigContentDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// CreateClusterKubeconfigContentDetailsEndpointEnum Enum with underlying type: string
|
||||
type CreateClusterKubeconfigContentDetailsEndpointEnum string
|
||||
|
||||
// Set of constants representing the allowable values for CreateClusterKubeconfigContentDetailsEndpointEnum
|
||||
const (
|
||||
CreateClusterKubeconfigContentDetailsEndpointLegacyKubernetes CreateClusterKubeconfigContentDetailsEndpointEnum = "LEGACY_KUBERNETES"
|
||||
CreateClusterKubeconfigContentDetailsEndpointPublicEndpoint CreateClusterKubeconfigContentDetailsEndpointEnum = "PUBLIC_ENDPOINT"
|
||||
CreateClusterKubeconfigContentDetailsEndpointPrivateEndpoint CreateClusterKubeconfigContentDetailsEndpointEnum = "PRIVATE_ENDPOINT"
|
||||
)
|
||||
|
||||
var mappingCreateClusterKubeconfigContentDetailsEndpoint = map[string]CreateClusterKubeconfigContentDetailsEndpointEnum{
|
||||
"LEGACY_KUBERNETES": CreateClusterKubeconfigContentDetailsEndpointLegacyKubernetes,
|
||||
"PUBLIC_ENDPOINT": CreateClusterKubeconfigContentDetailsEndpointPublicEndpoint,
|
||||
"PRIVATE_ENDPOINT": CreateClusterKubeconfigContentDetailsEndpointPrivateEndpoint,
|
||||
}
|
||||
|
||||
// GetCreateClusterKubeconfigContentDetailsEndpointEnumValues Enumerates the set of values for CreateClusterKubeconfigContentDetailsEndpointEnum
|
||||
func GetCreateClusterKubeconfigContentDetailsEndpointEnumValues() []CreateClusterKubeconfigContentDetailsEndpointEnum {
|
||||
values := make([]CreateClusterKubeconfigContentDetailsEndpointEnum, 0)
|
||||
for _, v := range mappingCreateClusterKubeconfigContentDetailsEndpoint {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CreateClusterRequest wrapper for the CreateCluster operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/CreateCluster.go.html to see an example of how to use CreateClusterRequest.
|
||||
type CreateClusterRequest struct {
|
||||
|
||||
// The details of the cluster to create.
|
||||
CreateClusterDetails `contributesTo:"body"`
|
||||
|
||||
// A token you supply to uniquely identify the request and provide idempotency if
|
||||
// the request is retried. Idempotency tokens expire after 24 hours.
|
||||
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request CreateClusterRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request CreateClusterRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request CreateClusterRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request CreateClusterRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// CreateClusterResponse wrapper for the CreateCluster operation
|
||||
type CreateClusterResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The OCID of the work request handling the operation.
|
||||
OpcWorkRequestId *string `presentIn:"header" name:"opc-work-request-id"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response CreateClusterResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response CreateClusterResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// CreateImagePolicyConfigDetails The properties that define a image verification policy.
|
||||
type CreateImagePolicyConfigDetails struct {
|
||||
|
||||
// Whether the image verification policy is enabled. Defaults to false. If set to true, the images will be verified against the policy at runtime.
|
||||
IsPolicyEnabled *bool `mandatory:"false" json:"isPolicyEnabled"`
|
||||
|
||||
// A list of KMS key details.
|
||||
KeyDetails []KeyDetails `mandatory:"false" json:"keyDetails"`
|
||||
}
|
||||
|
||||
func (m CreateImagePolicyConfigDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"io"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CreateKubeconfigRequest wrapper for the CreateKubeconfig operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/CreateKubeconfig.go.html to see an example of how to use CreateKubeconfigRequest.
|
||||
type CreateKubeconfigRequest struct {
|
||||
|
||||
// The OCID of the cluster.
|
||||
ClusterId *string `mandatory:"true" contributesTo:"path" name:"clusterId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// The details of the cluster kubeconfig to create.
|
||||
CreateClusterKubeconfigContentDetails `contributesTo:"body"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request CreateKubeconfigRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request CreateKubeconfigRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request CreateKubeconfigRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request CreateKubeconfigRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// CreateKubeconfigResponse wrapper for the CreateKubeconfig operation
|
||||
type CreateKubeconfigResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The io.ReadCloser instance
|
||||
Content io.ReadCloser `presentIn:"body" encoding:"binary"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response CreateKubeconfigResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response CreateKubeconfigResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// CreateNodePoolDetails The properties that define a request to create a node pool.
|
||||
type CreateNodePoolDetails struct {
|
||||
|
||||
// The OCID of the compartment in which the node pool exists.
|
||||
CompartmentId *string `mandatory:"true" json:"compartmentId"`
|
||||
|
||||
// The OCID of the cluster to which this node pool is attached.
|
||||
ClusterId *string `mandatory:"true" json:"clusterId"`
|
||||
|
||||
// The name of the node pool. Avoid entering confidential information.
|
||||
Name *string `mandatory:"true" json:"name"`
|
||||
|
||||
// The version of Kubernetes to install on the nodes in the node pool.
|
||||
KubernetesVersion *string `mandatory:"true" json:"kubernetesVersion"`
|
||||
|
||||
// The name of the node shape of the nodes in the node pool.
|
||||
NodeShape *string `mandatory:"true" json:"nodeShape"`
|
||||
|
||||
// A list of key/value pairs to add to each underlying OCI instance in the node pool on launch.
|
||||
NodeMetadata map[string]string `mandatory:"false" json:"nodeMetadata"`
|
||||
|
||||
// Deprecated. Use `nodeSourceDetails` instead.
|
||||
// If you specify values for both, this value is ignored.
|
||||
// The name of the image running on the nodes in the node pool.
|
||||
NodeImageName *string `mandatory:"false" json:"nodeImageName"`
|
||||
|
||||
// Specify the source to use to launch nodes in the node pool. Currently, image is the only supported source.
|
||||
NodeSourceDetails NodeSourceDetails `mandatory:"false" json:"nodeSourceDetails"`
|
||||
|
||||
// Specify the configuration of the shape to launch nodes in the node pool.
|
||||
NodeShapeConfig *CreateNodeShapeConfigDetails `mandatory:"false" json:"nodeShapeConfig"`
|
||||
|
||||
// A list of key/value pairs to add to nodes after they join the Kubernetes cluster.
|
||||
InitialNodeLabels []KeyValue `mandatory:"false" json:"initialNodeLabels"`
|
||||
|
||||
// The SSH public key on each node in the node pool on launch.
|
||||
SshPublicKey *string `mandatory:"false" json:"sshPublicKey"`
|
||||
|
||||
// Optional, default to 1. The number of nodes to create in each subnet specified in subnetIds property.
|
||||
// When used, subnetIds is required. This property is deprecated, use nodeConfigDetails instead.
|
||||
QuantityPerSubnet *int `mandatory:"false" json:"quantityPerSubnet"`
|
||||
|
||||
// The OCIDs of the subnets in which to place nodes for this node pool. When used, quantityPerSubnet
|
||||
// can be provided. This property is deprecated, use nodeConfigDetails. Exactly one of the
|
||||
// subnetIds or nodeConfigDetails properties must be specified.
|
||||
SubnetIds []string `mandatory:"false" json:"subnetIds"`
|
||||
|
||||
// The configuration of nodes in the node pool. Exactly one of the
|
||||
// subnetIds or nodeConfigDetails properties must be specified.
|
||||
NodeConfigDetails *CreateNodePoolNodeConfigDetails `mandatory:"false" json:"nodeConfigDetails"`
|
||||
}
|
||||
|
||||
func (m CreateNodePoolDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from json
|
||||
func (m *CreateNodePoolDetails) UnmarshalJSON(data []byte) (e error) {
|
||||
model := struct {
|
||||
NodeMetadata map[string]string `json:"nodeMetadata"`
|
||||
NodeImageName *string `json:"nodeImageName"`
|
||||
NodeSourceDetails nodesourcedetails `json:"nodeSourceDetails"`
|
||||
NodeShapeConfig *CreateNodeShapeConfigDetails `json:"nodeShapeConfig"`
|
||||
InitialNodeLabels []KeyValue `json:"initialNodeLabels"`
|
||||
SshPublicKey *string `json:"sshPublicKey"`
|
||||
QuantityPerSubnet *int `json:"quantityPerSubnet"`
|
||||
SubnetIds []string `json:"subnetIds"`
|
||||
NodeConfigDetails *CreateNodePoolNodeConfigDetails `json:"nodeConfigDetails"`
|
||||
CompartmentId *string `json:"compartmentId"`
|
||||
ClusterId *string `json:"clusterId"`
|
||||
Name *string `json:"name"`
|
||||
KubernetesVersion *string `json:"kubernetesVersion"`
|
||||
NodeShape *string `json:"nodeShape"`
|
||||
}{}
|
||||
|
||||
e = json.Unmarshal(data, &model)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
var nn interface{}
|
||||
m.NodeMetadata = model.NodeMetadata
|
||||
|
||||
m.NodeImageName = model.NodeImageName
|
||||
|
||||
nn, e = model.NodeSourceDetails.UnmarshalPolymorphicJSON(model.NodeSourceDetails.JsonData)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
if nn != nil {
|
||||
m.NodeSourceDetails = nn.(NodeSourceDetails)
|
||||
} else {
|
||||
m.NodeSourceDetails = nil
|
||||
}
|
||||
|
||||
m.NodeShapeConfig = model.NodeShapeConfig
|
||||
|
||||
m.InitialNodeLabels = make([]KeyValue, len(model.InitialNodeLabels))
|
||||
for i, n := range model.InitialNodeLabels {
|
||||
m.InitialNodeLabels[i] = n
|
||||
}
|
||||
|
||||
m.SshPublicKey = model.SshPublicKey
|
||||
|
||||
m.QuantityPerSubnet = model.QuantityPerSubnet
|
||||
|
||||
m.SubnetIds = make([]string, len(model.SubnetIds))
|
||||
for i, n := range model.SubnetIds {
|
||||
m.SubnetIds[i] = n
|
||||
}
|
||||
|
||||
m.NodeConfigDetails = model.NodeConfigDetails
|
||||
|
||||
m.CompartmentId = model.CompartmentId
|
||||
|
||||
m.ClusterId = model.ClusterId
|
||||
|
||||
m.Name = model.Name
|
||||
|
||||
m.KubernetesVersion = model.KubernetesVersion
|
||||
|
||||
m.NodeShape = model.NodeShape
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// CreateNodePoolNodeConfigDetails The size and placement configuration of nodes in the node pool.
|
||||
type CreateNodePoolNodeConfigDetails struct {
|
||||
|
||||
// The number of nodes that should be in the node pool.
|
||||
Size *int `mandatory:"true" json:"size"`
|
||||
|
||||
// The placement configurations for the node pool. Provide one placement
|
||||
// configuration for each availability domain in which you intend to launch a node.
|
||||
// To use the node pool with a regional subnet, provide a placement configuration for
|
||||
// each availability domain, and include the regional subnet in each placement
|
||||
// configuration.
|
||||
PlacementConfigs []NodePoolPlacementConfigDetails `mandatory:"true" json:"placementConfigs"`
|
||||
|
||||
// The OCIDs of the Network Security Group(s) to associate nodes for this node pool with. For more information about NSGs, see NetworkSecurityGroup.
|
||||
NsgIds []string `mandatory:"false" json:"nsgIds"`
|
||||
}
|
||||
|
||||
func (m CreateNodePoolNodeConfigDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// CreateNodePoolRequest wrapper for the CreateNodePool operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/CreateNodePool.go.html to see an example of how to use CreateNodePoolRequest.
|
||||
type CreateNodePoolRequest struct {
|
||||
|
||||
// The details of the node pool to create.
|
||||
CreateNodePoolDetails `contributesTo:"body"`
|
||||
|
||||
// A token you supply to uniquely identify the request and provide idempotency if
|
||||
// the request is retried. Idempotency tokens expire after 24 hours.
|
||||
OpcRetryToken *string `mandatory:"false" contributesTo:"header" name:"opc-retry-token"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request CreateNodePoolRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request CreateNodePoolRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request CreateNodePoolRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request CreateNodePoolRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// CreateNodePoolResponse wrapper for the CreateNodePool operation
|
||||
type CreateNodePoolResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The OCID of the work request handling the operation.
|
||||
OpcWorkRequestId *string `presentIn:"header" name:"opc-work-request-id"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response CreateNodePoolResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response CreateNodePoolResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// CreateNodeShapeConfigDetails The shape configuration of the nodes.
|
||||
type CreateNodeShapeConfigDetails struct {
|
||||
|
||||
// The total number of OCPUs available to each node in the node pool.
|
||||
// See here (https://docs.cloud.oracle.com/en-us/iaas/api/#/en/iaas/20160918/Shape/) for details.
|
||||
Ocpus *float32 `mandatory:"false" json:"ocpus"`
|
||||
|
||||
// The total amount of memory available to each node, in gigabytes.
|
||||
MemoryInGBs *float32 `mandatory:"false" json:"memoryInGBs"`
|
||||
}
|
||||
|
||||
func (m CreateNodeShapeConfigDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// DeleteClusterRequest wrapper for the DeleteCluster operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/DeleteCluster.go.html to see an example of how to use DeleteClusterRequest.
|
||||
type DeleteClusterRequest struct {
|
||||
|
||||
// The OCID of the cluster.
|
||||
ClusterId *string `mandatory:"true" contributesTo:"path" name:"clusterId"`
|
||||
|
||||
// For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match`
|
||||
// parameter to the value of the etag from a previous GET or POST response for that resource. The resource
|
||||
// will be updated or deleted only if the etag you provide matches the resource's current etag value.
|
||||
IfMatch *string `mandatory:"false" contributesTo:"header" name:"if-match"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request DeleteClusterRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request DeleteClusterRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request DeleteClusterRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request DeleteClusterRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// DeleteClusterResponse wrapper for the DeleteCluster operation
|
||||
type DeleteClusterResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The OCID of the work request handling the operation.
|
||||
OpcWorkRequestId *string `presentIn:"header" name:"opc-work-request-id"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response DeleteClusterResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response DeleteClusterResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// DeleteNodePoolRequest wrapper for the DeleteNodePool operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/DeleteNodePool.go.html to see an example of how to use DeleteNodePoolRequest.
|
||||
type DeleteNodePoolRequest struct {
|
||||
|
||||
// The OCID of the node pool.
|
||||
NodePoolId *string `mandatory:"true" contributesTo:"path" name:"nodePoolId"`
|
||||
|
||||
// For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match`
|
||||
// parameter to the value of the etag from a previous GET or POST response for that resource. The resource
|
||||
// will be updated or deleted only if the etag you provide matches the resource's current etag value.
|
||||
IfMatch *string `mandatory:"false" contributesTo:"header" name:"if-match"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request DeleteNodePoolRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request DeleteNodePoolRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request DeleteNodePoolRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request DeleteNodePoolRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// DeleteNodePoolResponse wrapper for the DeleteNodePool operation
|
||||
type DeleteNodePoolResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The OCID of the work request handling the operation.
|
||||
OpcWorkRequestId *string `presentIn:"header" name:"opc-work-request-id"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response DeleteNodePoolResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response DeleteNodePoolResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// DeleteWorkRequestRequest wrapper for the DeleteWorkRequest operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/DeleteWorkRequest.go.html to see an example of how to use DeleteWorkRequestRequest.
|
||||
type DeleteWorkRequestRequest struct {
|
||||
|
||||
// The OCID of the work request.
|
||||
WorkRequestId *string `mandatory:"true" contributesTo:"path" name:"workRequestId"`
|
||||
|
||||
// For optimistic concurrency control. In the PUT or DELETE call for a resource, set the `if-match`
|
||||
// parameter to the value of the etag from a previous GET or POST response for that resource. The resource
|
||||
// will be updated or deleted only if the etag you provide matches the resource's current etag value.
|
||||
IfMatch *string `mandatory:"false" contributesTo:"header" name:"if-match"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request DeleteWorkRequestRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request DeleteWorkRequestRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request DeleteWorkRequestRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request DeleteWorkRequestRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// DeleteWorkRequestResponse wrapper for the DeleteWorkRequest operation
|
||||
type DeleteWorkRequestResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response DeleteWorkRequestResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response DeleteWorkRequestResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetClusterMigrateToNativeVcnStatusRequest wrapper for the GetClusterMigrateToNativeVcnStatus operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/GetClusterMigrateToNativeVcnStatus.go.html to see an example of how to use GetClusterMigrateToNativeVcnStatusRequest.
|
||||
type GetClusterMigrateToNativeVcnStatusRequest struct {
|
||||
|
||||
// The OCID of the cluster.
|
||||
ClusterId *string `mandatory:"true" contributesTo:"path" name:"clusterId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request GetClusterMigrateToNativeVcnStatusRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request GetClusterMigrateToNativeVcnStatusRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request GetClusterMigrateToNativeVcnStatusRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request GetClusterMigrateToNativeVcnStatusRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// GetClusterMigrateToNativeVcnStatusResponse wrapper for the GetClusterMigrateToNativeVcnStatus operation
|
||||
type GetClusterMigrateToNativeVcnStatusResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The ClusterMigrateToNativeVcnStatus instance
|
||||
ClusterMigrateToNativeVcnStatus `presentIn:"body"`
|
||||
|
||||
// For optimistic concurrency control. See `if-match`.
|
||||
Etag *string `presentIn:"header" name:"etag"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response GetClusterMigrateToNativeVcnStatusResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response GetClusterMigrateToNativeVcnStatusResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetClusterOptionsRequest wrapper for the GetClusterOptions operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/GetClusterOptions.go.html to see an example of how to use GetClusterOptionsRequest.
|
||||
type GetClusterOptionsRequest struct {
|
||||
|
||||
// The id of the option set to retrieve. Use "all" get all options, or use a cluster ID to get options specific to the provided cluster.
|
||||
ClusterOptionId *string `mandatory:"true" contributesTo:"path" name:"clusterOptionId"`
|
||||
|
||||
// The OCID of the compartment.
|
||||
CompartmentId *string `mandatory:"false" contributesTo:"query" name:"compartmentId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request GetClusterOptionsRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request GetClusterOptionsRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request GetClusterOptionsRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request GetClusterOptionsRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// GetClusterOptionsResponse wrapper for the GetClusterOptions operation
|
||||
type GetClusterOptionsResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The ClusterOptions instance
|
||||
ClusterOptions `presentIn:"body"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response GetClusterOptionsResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response GetClusterOptionsResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetClusterRequest wrapper for the GetCluster operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/GetCluster.go.html to see an example of how to use GetClusterRequest.
|
||||
type GetClusterRequest struct {
|
||||
|
||||
// The OCID of the cluster.
|
||||
ClusterId *string `mandatory:"true" contributesTo:"path" name:"clusterId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request GetClusterRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request GetClusterRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request GetClusterRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request GetClusterRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// GetClusterResponse wrapper for the GetCluster operation
|
||||
type GetClusterResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The Cluster instance
|
||||
Cluster `presentIn:"body"`
|
||||
|
||||
// For optimistic concurrency control. See `if-match`.
|
||||
Etag *string `presentIn:"header" name:"etag"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response GetClusterResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response GetClusterResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetNodePoolOptionsRequest wrapper for the GetNodePoolOptions operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/GetNodePoolOptions.go.html to see an example of how to use GetNodePoolOptionsRequest.
|
||||
type GetNodePoolOptionsRequest struct {
|
||||
|
||||
// The id of the option set to retrieve. Use "all" get all options, or use a cluster ID to get options specific to the provided cluster.
|
||||
NodePoolOptionId *string `mandatory:"true" contributesTo:"path" name:"nodePoolOptionId"`
|
||||
|
||||
// The OCID of the compartment.
|
||||
CompartmentId *string `mandatory:"false" contributesTo:"query" name:"compartmentId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request GetNodePoolOptionsRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request GetNodePoolOptionsRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request GetNodePoolOptionsRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request GetNodePoolOptionsRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// GetNodePoolOptionsResponse wrapper for the GetNodePoolOptions operation
|
||||
type GetNodePoolOptionsResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The NodePoolOptions instance
|
||||
NodePoolOptions `presentIn:"body"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response GetNodePoolOptionsResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response GetNodePoolOptionsResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetNodePoolRequest wrapper for the GetNodePool operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/GetNodePool.go.html to see an example of how to use GetNodePoolRequest.
|
||||
type GetNodePoolRequest struct {
|
||||
|
||||
// The OCID of the node pool.
|
||||
NodePoolId *string `mandatory:"true" contributesTo:"path" name:"nodePoolId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request GetNodePoolRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request GetNodePoolRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request GetNodePoolRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request GetNodePoolRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// GetNodePoolResponse wrapper for the GetNodePool operation
|
||||
type GetNodePoolResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The NodePool instance
|
||||
NodePool `presentIn:"body"`
|
||||
|
||||
// For optimistic concurrency control. See `if-match`.
|
||||
Etag *string `presentIn:"header" name:"etag"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response GetNodePoolResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response GetNodePoolResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// GetWorkRequestRequest wrapper for the GetWorkRequest operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/GetWorkRequest.go.html to see an example of how to use GetWorkRequestRequest.
|
||||
type GetWorkRequestRequest struct {
|
||||
|
||||
// The OCID of the work request.
|
||||
WorkRequestId *string `mandatory:"true" contributesTo:"path" name:"workRequestId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request GetWorkRequestRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request GetWorkRequestRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request GetWorkRequestRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request GetWorkRequestRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// GetWorkRequestResponse wrapper for the GetWorkRequest operation
|
||||
type GetWorkRequestResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The WorkRequest instance
|
||||
WorkRequest `presentIn:"body"`
|
||||
|
||||
// For optimistic concurrency control. See `if-match`.
|
||||
Etag *string `presentIn:"header" name:"etag"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
|
||||
// the number of seconds to should wait before polling this endpoint again
|
||||
RetryAfter *int `presentIn:"header" name:"retry-after"`
|
||||
}
|
||||
|
||||
func (response GetWorkRequestResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response GetWorkRequestResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// ImagePolicyConfig The properties that define a image verification policy.
|
||||
type ImagePolicyConfig struct {
|
||||
|
||||
// Whether the image verification policy is enabled. Defaults to false. If set to true, the images will be verified against the policy at runtime.
|
||||
IsPolicyEnabled *bool `mandatory:"false" json:"isPolicyEnabled"`
|
||||
|
||||
// A list of KMS key details.
|
||||
KeyDetails []KeyDetails `mandatory:"false" json:"keyDetails"`
|
||||
}
|
||||
|
||||
func (m ImagePolicyConfig) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// KeyDetails The properties that define the kms keys used by OKE for Image Signature verification.
|
||||
type KeyDetails struct {
|
||||
|
||||
// The OCIDs of the KMS key that will be used to verify whether the images are signed by an approved source.
|
||||
KmsKeyId *string `mandatory:"false" json:"kmsKeyId"`
|
||||
}
|
||||
|
||||
func (m KeyDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// KeyValue The properties that define a key value pair.
|
||||
type KeyValue struct {
|
||||
|
||||
// The key of the pair.
|
||||
Key *string `mandatory:"false" json:"key"`
|
||||
|
||||
// The value of the pair.
|
||||
Value *string `mandatory:"false" json:"value"`
|
||||
}
|
||||
|
||||
func (m KeyValue) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// KubernetesNetworkConfig The properties that define the network configuration for Kubernetes.
|
||||
type KubernetesNetworkConfig struct {
|
||||
|
||||
// The CIDR block for Kubernetes pods.
|
||||
PodsCidr *string `mandatory:"false" json:"podsCidr"`
|
||||
|
||||
// The CIDR block for Kubernetes services.
|
||||
ServicesCidr *string `mandatory:"false" json:"servicesCidr"`
|
||||
}
|
||||
|
||||
func (m KubernetesNetworkConfig) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ListClustersRequest wrapper for the ListClusters operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/ListClusters.go.html to see an example of how to use ListClustersRequest.
|
||||
type ListClustersRequest struct {
|
||||
|
||||
// The OCID of the compartment.
|
||||
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
|
||||
|
||||
// A cluster lifecycle state to filter on. Can have multiple parameters of this name.
|
||||
LifecycleState []ClusterLifecycleStateEnum `contributesTo:"query" name:"lifecycleState" omitEmpty:"true" collectionFormat:"multi"`
|
||||
|
||||
// The name to filter on.
|
||||
Name *string `mandatory:"false" contributesTo:"query" name:"name"`
|
||||
|
||||
// For list pagination. The maximum number of results per page, or items to return in a paginated "List" call.
|
||||
// 1 is the minimum, 1000 is the maximum. For important details about how pagination works,
|
||||
// see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
Limit *int `mandatory:"false" contributesTo:"query" name:"limit"`
|
||||
|
||||
// For list pagination. The value of the `opc-next-page` response header from the previous "List" call.
|
||||
// For important details about how pagination works, see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
Page *string `mandatory:"false" contributesTo:"query" name:"page"`
|
||||
|
||||
// The optional order in which to sort the results.
|
||||
SortOrder ListClustersSortOrderEnum `mandatory:"false" contributesTo:"query" name:"sortOrder" omitEmpty:"true"`
|
||||
|
||||
// The optional field to sort the results by.
|
||||
SortBy ListClustersSortByEnum `mandatory:"false" contributesTo:"query" name:"sortBy" omitEmpty:"true"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request ListClustersRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request ListClustersRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request ListClustersRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request ListClustersRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// ListClustersResponse wrapper for the ListClusters operation
|
||||
type ListClustersResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// A list of []ClusterSummary instances
|
||||
Items []ClusterSummary `presentIn:"body"`
|
||||
|
||||
// For list pagination. When this header appears in the response, additional pages of results remain.
|
||||
// For important details about how pagination works, see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
OpcNextPage *string `presentIn:"header" name:"opc-next-page"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response ListClustersResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response ListClustersResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
||||
// ListClustersSortOrderEnum Enum with underlying type: string
|
||||
type ListClustersSortOrderEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ListClustersSortOrderEnum
|
||||
const (
|
||||
ListClustersSortOrderAsc ListClustersSortOrderEnum = "ASC"
|
||||
ListClustersSortOrderDesc ListClustersSortOrderEnum = "DESC"
|
||||
)
|
||||
|
||||
var mappingListClustersSortOrder = map[string]ListClustersSortOrderEnum{
|
||||
"ASC": ListClustersSortOrderAsc,
|
||||
"DESC": ListClustersSortOrderDesc,
|
||||
}
|
||||
|
||||
// GetListClustersSortOrderEnumValues Enumerates the set of values for ListClustersSortOrderEnum
|
||||
func GetListClustersSortOrderEnumValues() []ListClustersSortOrderEnum {
|
||||
values := make([]ListClustersSortOrderEnum, 0)
|
||||
for _, v := range mappingListClustersSortOrder {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// ListClustersSortByEnum Enum with underlying type: string
|
||||
type ListClustersSortByEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ListClustersSortByEnum
|
||||
const (
|
||||
ListClustersSortById ListClustersSortByEnum = "ID"
|
||||
ListClustersSortByName ListClustersSortByEnum = "NAME"
|
||||
ListClustersSortByTimeCreated ListClustersSortByEnum = "TIME_CREATED"
|
||||
)
|
||||
|
||||
var mappingListClustersSortBy = map[string]ListClustersSortByEnum{
|
||||
"ID": ListClustersSortById,
|
||||
"NAME": ListClustersSortByName,
|
||||
"TIME_CREATED": ListClustersSortByTimeCreated,
|
||||
}
|
||||
|
||||
// GetListClustersSortByEnumValues Enumerates the set of values for ListClustersSortByEnum
|
||||
func GetListClustersSortByEnumValues() []ListClustersSortByEnum {
|
||||
values := make([]ListClustersSortByEnum, 0)
|
||||
for _, v := range mappingListClustersSortBy {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ListNodePoolsRequest wrapper for the ListNodePools operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/ListNodePools.go.html to see an example of how to use ListNodePoolsRequest.
|
||||
type ListNodePoolsRequest struct {
|
||||
|
||||
// The OCID of the compartment.
|
||||
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
|
||||
|
||||
// The OCID of the cluster.
|
||||
ClusterId *string `mandatory:"false" contributesTo:"query" name:"clusterId"`
|
||||
|
||||
// The name to filter on.
|
||||
Name *string `mandatory:"false" contributesTo:"query" name:"name"`
|
||||
|
||||
// For list pagination. The maximum number of results per page, or items to return in a paginated "List" call.
|
||||
// 1 is the minimum, 1000 is the maximum. For important details about how pagination works,
|
||||
// see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
Limit *int `mandatory:"false" contributesTo:"query" name:"limit"`
|
||||
|
||||
// For list pagination. The value of the `opc-next-page` response header from the previous "List" call.
|
||||
// For important details about how pagination works, see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
Page *string `mandatory:"false" contributesTo:"query" name:"page"`
|
||||
|
||||
// The optional order in which to sort the results.
|
||||
SortOrder ListNodePoolsSortOrderEnum `mandatory:"false" contributesTo:"query" name:"sortOrder" omitEmpty:"true"`
|
||||
|
||||
// The optional field to sort the results by.
|
||||
SortBy ListNodePoolsSortByEnum `mandatory:"false" contributesTo:"query" name:"sortBy" omitEmpty:"true"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request ListNodePoolsRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request ListNodePoolsRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request ListNodePoolsRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request ListNodePoolsRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// ListNodePoolsResponse wrapper for the ListNodePools operation
|
||||
type ListNodePoolsResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// A list of []NodePoolSummary instances
|
||||
Items []NodePoolSummary `presentIn:"body"`
|
||||
|
||||
// For list pagination. When this header appears in the response, additional pages of results remain.
|
||||
// For important details about how pagination works, see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
OpcNextPage *string `presentIn:"header" name:"opc-next-page"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response ListNodePoolsResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response ListNodePoolsResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
||||
// ListNodePoolsSortOrderEnum Enum with underlying type: string
|
||||
type ListNodePoolsSortOrderEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ListNodePoolsSortOrderEnum
|
||||
const (
|
||||
ListNodePoolsSortOrderAsc ListNodePoolsSortOrderEnum = "ASC"
|
||||
ListNodePoolsSortOrderDesc ListNodePoolsSortOrderEnum = "DESC"
|
||||
)
|
||||
|
||||
var mappingListNodePoolsSortOrder = map[string]ListNodePoolsSortOrderEnum{
|
||||
"ASC": ListNodePoolsSortOrderAsc,
|
||||
"DESC": ListNodePoolsSortOrderDesc,
|
||||
}
|
||||
|
||||
// GetListNodePoolsSortOrderEnumValues Enumerates the set of values for ListNodePoolsSortOrderEnum
|
||||
func GetListNodePoolsSortOrderEnumValues() []ListNodePoolsSortOrderEnum {
|
||||
values := make([]ListNodePoolsSortOrderEnum, 0)
|
||||
for _, v := range mappingListNodePoolsSortOrder {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// ListNodePoolsSortByEnum Enum with underlying type: string
|
||||
type ListNodePoolsSortByEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ListNodePoolsSortByEnum
|
||||
const (
|
||||
ListNodePoolsSortById ListNodePoolsSortByEnum = "ID"
|
||||
ListNodePoolsSortByName ListNodePoolsSortByEnum = "NAME"
|
||||
ListNodePoolsSortByTimeCreated ListNodePoolsSortByEnum = "TIME_CREATED"
|
||||
)
|
||||
|
||||
var mappingListNodePoolsSortBy = map[string]ListNodePoolsSortByEnum{
|
||||
"ID": ListNodePoolsSortById,
|
||||
"NAME": ListNodePoolsSortByName,
|
||||
"TIME_CREATED": ListNodePoolsSortByTimeCreated,
|
||||
}
|
||||
|
||||
// GetListNodePoolsSortByEnumValues Enumerates the set of values for ListNodePoolsSortByEnum
|
||||
func GetListNodePoolsSortByEnumValues() []ListNodePoolsSortByEnum {
|
||||
values := make([]ListNodePoolsSortByEnum, 0)
|
||||
for _, v := range mappingListNodePoolsSortBy {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ListWorkRequestErrorsRequest wrapper for the ListWorkRequestErrors operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/ListWorkRequestErrors.go.html to see an example of how to use ListWorkRequestErrorsRequest.
|
||||
type ListWorkRequestErrorsRequest struct {
|
||||
|
||||
// The OCID of the compartment.
|
||||
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
|
||||
|
||||
// The OCID of the work request.
|
||||
WorkRequestId *string `mandatory:"true" contributesTo:"path" name:"workRequestId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request ListWorkRequestErrorsRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request ListWorkRequestErrorsRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request ListWorkRequestErrorsRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request ListWorkRequestErrorsRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// ListWorkRequestErrorsResponse wrapper for the ListWorkRequestErrors operation
|
||||
type ListWorkRequestErrorsResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The []WorkRequestError instance
|
||||
Items []WorkRequestError `presentIn:"body"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response ListWorkRequestErrorsResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response ListWorkRequestErrorsResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ListWorkRequestLogsRequest wrapper for the ListWorkRequestLogs operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/ListWorkRequestLogs.go.html to see an example of how to use ListWorkRequestLogsRequest.
|
||||
type ListWorkRequestLogsRequest struct {
|
||||
|
||||
// The OCID of the compartment.
|
||||
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
|
||||
|
||||
// The OCID of the work request.
|
||||
WorkRequestId *string `mandatory:"true" contributesTo:"path" name:"workRequestId"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request ListWorkRequestLogsRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request ListWorkRequestLogsRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request ListWorkRequestLogsRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request ListWorkRequestLogsRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// ListWorkRequestLogsResponse wrapper for the ListWorkRequestLogs operation
|
||||
type ListWorkRequestLogsResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// The []WorkRequestLogEntry instance
|
||||
Items []WorkRequestLogEntry `presentIn:"body"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response ListWorkRequestLogsResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response ListWorkRequestLogsResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// ListWorkRequestsRequest wrapper for the ListWorkRequests operation
|
||||
//
|
||||
// See also
|
||||
//
|
||||
// Click https://docs.cloud.oracle.com/en-us/iaas/tools/go-sdk-examples/latest/containerengine/ListWorkRequests.go.html to see an example of how to use ListWorkRequestsRequest.
|
||||
type ListWorkRequestsRequest struct {
|
||||
|
||||
// The OCID of the compartment.
|
||||
CompartmentId *string `mandatory:"true" contributesTo:"query" name:"compartmentId"`
|
||||
|
||||
// The OCID of the cluster.
|
||||
ClusterId *string `mandatory:"false" contributesTo:"query" name:"clusterId"`
|
||||
|
||||
// The OCID of the resource associated with a work request
|
||||
ResourceId *string `mandatory:"false" contributesTo:"query" name:"resourceId"`
|
||||
|
||||
// Type of the resource associated with a work request
|
||||
ResourceType ListWorkRequestsResourceTypeEnum `mandatory:"false" contributesTo:"query" name:"resourceType" omitEmpty:"true"`
|
||||
|
||||
// A work request status to filter on. Can have multiple parameters of this name.
|
||||
Status []string `contributesTo:"query" name:"status" collectionFormat:"multi"`
|
||||
|
||||
// For list pagination. The maximum number of results per page, or items to return in a paginated "List" call.
|
||||
// 1 is the minimum, 1000 is the maximum. For important details about how pagination works,
|
||||
// see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
Limit *int `mandatory:"false" contributesTo:"query" name:"limit"`
|
||||
|
||||
// For list pagination. The value of the `opc-next-page` response header from the previous "List" call.
|
||||
// For important details about how pagination works, see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
Page *string `mandatory:"false" contributesTo:"query" name:"page"`
|
||||
|
||||
// The optional order in which to sort the results.
|
||||
SortOrder ListWorkRequestsSortOrderEnum `mandatory:"false" contributesTo:"query" name:"sortOrder" omitEmpty:"true"`
|
||||
|
||||
// The optional field to sort the results by.
|
||||
SortBy ListWorkRequestsSortByEnum `mandatory:"false" contributesTo:"query" name:"sortBy" omitEmpty:"true"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact
|
||||
// Oracle about a particular request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" contributesTo:"header" name:"opc-request-id"`
|
||||
|
||||
// Metadata about the request. This information will not be transmitted to the service, but
|
||||
// represents information that the SDK will consume to drive retry behavior.
|
||||
RequestMetadata common.RequestMetadata
|
||||
}
|
||||
|
||||
func (request ListWorkRequestsRequest) String() string {
|
||||
return common.PointerString(request)
|
||||
}
|
||||
|
||||
// HTTPRequest implements the OCIRequest interface
|
||||
func (request ListWorkRequestsRequest) HTTPRequest(method, path string, binaryRequestBody *common.OCIReadSeekCloser) (http.Request, error) {
|
||||
|
||||
return common.MakeDefaultHTTPRequestWithTaggedStruct(method, path, request)
|
||||
}
|
||||
|
||||
// BinaryRequestBody implements the OCIRequest interface
|
||||
func (request ListWorkRequestsRequest) BinaryRequestBody() (*common.OCIReadSeekCloser, bool) {
|
||||
|
||||
return nil, false
|
||||
|
||||
}
|
||||
|
||||
// RetryPolicy implements the OCIRetryableRequest interface. This retrieves the specified retry policy.
|
||||
func (request ListWorkRequestsRequest) RetryPolicy() *common.RetryPolicy {
|
||||
return request.RequestMetadata.RetryPolicy
|
||||
}
|
||||
|
||||
// ListWorkRequestsResponse wrapper for the ListWorkRequests operation
|
||||
type ListWorkRequestsResponse struct {
|
||||
|
||||
// The underlying http response
|
||||
RawResponse *http.Response
|
||||
|
||||
// A list of []WorkRequestSummary instances
|
||||
Items []WorkRequestSummary `presentIn:"body"`
|
||||
|
||||
// For list pagination. When this header appears in the response, additional pages of results remain.
|
||||
// For important details about how pagination works, see List Pagination (https://docs.cloud.oracle.com/iaas/Content/API/Concepts/usingapi.htm#nine).
|
||||
OpcNextPage *string `presentIn:"header" name:"opc-next-page"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the request. If you need to contact Oracle about a
|
||||
// particular request, please provide the request ID.
|
||||
OpcRequestId *string `presentIn:"header" name:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (response ListWorkRequestsResponse) String() string {
|
||||
return common.PointerString(response)
|
||||
}
|
||||
|
||||
// HTTPResponse implements the OCIResponse interface
|
||||
func (response ListWorkRequestsResponse) HTTPResponse() *http.Response {
|
||||
return response.RawResponse
|
||||
}
|
||||
|
||||
// ListWorkRequestsResourceTypeEnum Enum with underlying type: string
|
||||
type ListWorkRequestsResourceTypeEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ListWorkRequestsResourceTypeEnum
|
||||
const (
|
||||
ListWorkRequestsResourceTypeCluster ListWorkRequestsResourceTypeEnum = "CLUSTER"
|
||||
ListWorkRequestsResourceTypeNodepool ListWorkRequestsResourceTypeEnum = "NODEPOOL"
|
||||
)
|
||||
|
||||
var mappingListWorkRequestsResourceType = map[string]ListWorkRequestsResourceTypeEnum{
|
||||
"CLUSTER": ListWorkRequestsResourceTypeCluster,
|
||||
"NODEPOOL": ListWorkRequestsResourceTypeNodepool,
|
||||
}
|
||||
|
||||
// GetListWorkRequestsResourceTypeEnumValues Enumerates the set of values for ListWorkRequestsResourceTypeEnum
|
||||
func GetListWorkRequestsResourceTypeEnumValues() []ListWorkRequestsResourceTypeEnum {
|
||||
values := make([]ListWorkRequestsResourceTypeEnum, 0)
|
||||
for _, v := range mappingListWorkRequestsResourceType {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// ListWorkRequestsSortOrderEnum Enum with underlying type: string
|
||||
type ListWorkRequestsSortOrderEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ListWorkRequestsSortOrderEnum
|
||||
const (
|
||||
ListWorkRequestsSortOrderAsc ListWorkRequestsSortOrderEnum = "ASC"
|
||||
ListWorkRequestsSortOrderDesc ListWorkRequestsSortOrderEnum = "DESC"
|
||||
)
|
||||
|
||||
var mappingListWorkRequestsSortOrder = map[string]ListWorkRequestsSortOrderEnum{
|
||||
"ASC": ListWorkRequestsSortOrderAsc,
|
||||
"DESC": ListWorkRequestsSortOrderDesc,
|
||||
}
|
||||
|
||||
// GetListWorkRequestsSortOrderEnumValues Enumerates the set of values for ListWorkRequestsSortOrderEnum
|
||||
func GetListWorkRequestsSortOrderEnumValues() []ListWorkRequestsSortOrderEnum {
|
||||
values := make([]ListWorkRequestsSortOrderEnum, 0)
|
||||
for _, v := range mappingListWorkRequestsSortOrder {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// ListWorkRequestsSortByEnum Enum with underlying type: string
|
||||
type ListWorkRequestsSortByEnum string
|
||||
|
||||
// Set of constants representing the allowable values for ListWorkRequestsSortByEnum
|
||||
const (
|
||||
ListWorkRequestsSortById ListWorkRequestsSortByEnum = "ID"
|
||||
ListWorkRequestsSortByOperationType ListWorkRequestsSortByEnum = "OPERATION_TYPE"
|
||||
ListWorkRequestsSortByStatus ListWorkRequestsSortByEnum = "STATUS"
|
||||
ListWorkRequestsSortByTimeAccepted ListWorkRequestsSortByEnum = "TIME_ACCEPTED"
|
||||
ListWorkRequestsSortByTimeStarted ListWorkRequestsSortByEnum = "TIME_STARTED"
|
||||
ListWorkRequestsSortByTimeFinished ListWorkRequestsSortByEnum = "TIME_FINISHED"
|
||||
)
|
||||
|
||||
var mappingListWorkRequestsSortBy = map[string]ListWorkRequestsSortByEnum{
|
||||
"ID": ListWorkRequestsSortById,
|
||||
"OPERATION_TYPE": ListWorkRequestsSortByOperationType,
|
||||
"STATUS": ListWorkRequestsSortByStatus,
|
||||
"TIME_ACCEPTED": ListWorkRequestsSortByTimeAccepted,
|
||||
"TIME_STARTED": ListWorkRequestsSortByTimeStarted,
|
||||
"TIME_FINISHED": ListWorkRequestsSortByTimeFinished,
|
||||
}
|
||||
|
||||
// GetListWorkRequestsSortByEnumValues Enumerates the set of values for ListWorkRequestsSortByEnum
|
||||
func GetListWorkRequestsSortByEnumValues() []ListWorkRequestsSortByEnum {
|
||||
values := make([]ListWorkRequestsSortByEnum, 0)
|
||||
for _, v := range mappingListWorkRequestsSortBy {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// Node The properties that define a node.
|
||||
type Node struct {
|
||||
|
||||
// The OCID of the compute instance backing this node.
|
||||
Id *string `mandatory:"false" json:"id"`
|
||||
|
||||
// The name of the node.
|
||||
Name *string `mandatory:"false" json:"name"`
|
||||
|
||||
// The version of Kubernetes this node is running.
|
||||
KubernetesVersion *string `mandatory:"false" json:"kubernetesVersion"`
|
||||
|
||||
// The name of the availability domain in which this node is placed.
|
||||
AvailabilityDomain *string `mandatory:"false" json:"availabilityDomain"`
|
||||
|
||||
// The OCID of the subnet in which this node is placed.
|
||||
SubnetId *string `mandatory:"false" json:"subnetId"`
|
||||
|
||||
// The OCID of the node pool to which this node belongs.
|
||||
NodePoolId *string `mandatory:"false" json:"nodePoolId"`
|
||||
|
||||
// The fault domain of this node.
|
||||
FaultDomain *string `mandatory:"false" json:"faultDomain"`
|
||||
|
||||
// The private IP address of this node.
|
||||
PrivateIp *string `mandatory:"false" json:"privateIp"`
|
||||
|
||||
// The public IP address of this node.
|
||||
PublicIp *string `mandatory:"false" json:"publicIp"`
|
||||
|
||||
// An error that may be associated with the node.
|
||||
NodeError *NodeError `mandatory:"false" json:"nodeError"`
|
||||
|
||||
// The state of the node.
|
||||
LifecycleState NodeLifecycleStateEnum `mandatory:"false" json:"lifecycleState,omitempty"`
|
||||
|
||||
// Details about the state of the node.
|
||||
LifecycleDetails *string `mandatory:"false" json:"lifecycleDetails"`
|
||||
}
|
||||
|
||||
func (m Node) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// NodeLifecycleStateEnum Enum with underlying type: string
|
||||
type NodeLifecycleStateEnum string
|
||||
|
||||
// Set of constants representing the allowable values for NodeLifecycleStateEnum
|
||||
const (
|
||||
NodeLifecycleStateCreating NodeLifecycleStateEnum = "CREATING"
|
||||
NodeLifecycleStateActive NodeLifecycleStateEnum = "ACTIVE"
|
||||
NodeLifecycleStateUpdating NodeLifecycleStateEnum = "UPDATING"
|
||||
NodeLifecycleStateDeleting NodeLifecycleStateEnum = "DELETING"
|
||||
NodeLifecycleStateDeleted NodeLifecycleStateEnum = "DELETED"
|
||||
NodeLifecycleStateFailing NodeLifecycleStateEnum = "FAILING"
|
||||
NodeLifecycleStateInactive NodeLifecycleStateEnum = "INACTIVE"
|
||||
)
|
||||
|
||||
var mappingNodeLifecycleState = map[string]NodeLifecycleStateEnum{
|
||||
"CREATING": NodeLifecycleStateCreating,
|
||||
"ACTIVE": NodeLifecycleStateActive,
|
||||
"UPDATING": NodeLifecycleStateUpdating,
|
||||
"DELETING": NodeLifecycleStateDeleting,
|
||||
"DELETED": NodeLifecycleStateDeleted,
|
||||
"FAILING": NodeLifecycleStateFailing,
|
||||
"INACTIVE": NodeLifecycleStateInactive,
|
||||
}
|
||||
|
||||
// GetNodeLifecycleStateEnumValues Enumerates the set of values for NodeLifecycleStateEnum
|
||||
func GetNodeLifecycleStateEnumValues() []NodeLifecycleStateEnum {
|
||||
values := make([]NodeLifecycleStateEnum, 0)
|
||||
for _, v := range mappingNodeLifecycleState {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodeError The properties that define an upstream error while managing a node.
|
||||
type NodeError struct {
|
||||
|
||||
// A short error code that defines the upstream error, meant for programmatic parsing. See API Errors (https://docs.cloud.oracle.com/Content/API/References/apierrors.htm).
|
||||
Code *string `mandatory:"true" json:"code"`
|
||||
|
||||
// A human-readable error string of the upstream error.
|
||||
Message *string `mandatory:"true" json:"message"`
|
||||
|
||||
// The status of the HTTP response encountered in the upstream error.
|
||||
Status *string `mandatory:"false" json:"status"`
|
||||
|
||||
// Unique Oracle-assigned identifier for the upstream request. If you need to contact Oracle about a particular upstream request, please provide the request ID.
|
||||
OpcRequestId *string `mandatory:"false" json:"opc-request-id"`
|
||||
}
|
||||
|
||||
func (m NodeError) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodePool A pool of compute nodes attached to a cluster. Avoid entering confidential information.
|
||||
type NodePool struct {
|
||||
|
||||
// The OCID of the node pool.
|
||||
Id *string `mandatory:"false" json:"id"`
|
||||
|
||||
// The OCID of the compartment in which the node pool exists.
|
||||
CompartmentId *string `mandatory:"false" json:"compartmentId"`
|
||||
|
||||
// The OCID of the cluster to which this node pool is attached.
|
||||
ClusterId *string `mandatory:"false" json:"clusterId"`
|
||||
|
||||
// The name of the node pool.
|
||||
Name *string `mandatory:"false" json:"name"`
|
||||
|
||||
// The version of Kubernetes running on the nodes in the node pool.
|
||||
KubernetesVersion *string `mandatory:"false" json:"kubernetesVersion"`
|
||||
|
||||
// A list of key/value pairs to add to each underlying OCI instance in the node pool on launch.
|
||||
NodeMetadata map[string]string `mandatory:"false" json:"nodeMetadata"`
|
||||
|
||||
// Deprecated. see `nodeSource`. The OCID of the image running on the nodes in the node pool.
|
||||
NodeImageId *string `mandatory:"false" json:"nodeImageId"`
|
||||
|
||||
// Deprecated. see `nodeSource`. The name of the image running on the nodes in the node pool.
|
||||
NodeImageName *string `mandatory:"false" json:"nodeImageName"`
|
||||
|
||||
// The shape configuration of the nodes.
|
||||
NodeShapeConfig *NodeShapeConfig `mandatory:"false" json:"nodeShapeConfig"`
|
||||
|
||||
// Deprecated. see `nodeSourceDetails`. Source running on the nodes in the node pool.
|
||||
NodeSource NodeSourceOption `mandatory:"false" json:"nodeSource"`
|
||||
|
||||
// Source running on the nodes in the node pool.
|
||||
NodeSourceDetails NodeSourceDetails `mandatory:"false" json:"nodeSourceDetails"`
|
||||
|
||||
// The name of the node shape of the nodes in the node pool.
|
||||
NodeShape *string `mandatory:"false" json:"nodeShape"`
|
||||
|
||||
// A list of key/value pairs to add to nodes after they join the Kubernetes cluster.
|
||||
InitialNodeLabels []KeyValue `mandatory:"false" json:"initialNodeLabels"`
|
||||
|
||||
// The SSH public key on each node in the node pool on launch.
|
||||
SshPublicKey *string `mandatory:"false" json:"sshPublicKey"`
|
||||
|
||||
// The number of nodes in each subnet.
|
||||
QuantityPerSubnet *int `mandatory:"false" json:"quantityPerSubnet"`
|
||||
|
||||
// The OCIDs of the subnets in which to place nodes for this node pool.
|
||||
SubnetIds []string `mandatory:"false" json:"subnetIds"`
|
||||
|
||||
// The nodes in the node pool.
|
||||
Nodes []Node `mandatory:"false" json:"nodes"`
|
||||
|
||||
// The configuration of nodes in the node pool.
|
||||
NodeConfigDetails *NodePoolNodeConfigDetails `mandatory:"false" json:"nodeConfigDetails"`
|
||||
}
|
||||
|
||||
func (m NodePool) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from json
|
||||
func (m *NodePool) UnmarshalJSON(data []byte) (e error) {
|
||||
model := struct {
|
||||
Id *string `json:"id"`
|
||||
CompartmentId *string `json:"compartmentId"`
|
||||
ClusterId *string `json:"clusterId"`
|
||||
Name *string `json:"name"`
|
||||
KubernetesVersion *string `json:"kubernetesVersion"`
|
||||
NodeMetadata map[string]string `json:"nodeMetadata"`
|
||||
NodeImageId *string `json:"nodeImageId"`
|
||||
NodeImageName *string `json:"nodeImageName"`
|
||||
NodeShapeConfig *NodeShapeConfig `json:"nodeShapeConfig"`
|
||||
NodeSource nodesourceoption `json:"nodeSource"`
|
||||
NodeSourceDetails nodesourcedetails `json:"nodeSourceDetails"`
|
||||
NodeShape *string `json:"nodeShape"`
|
||||
InitialNodeLabels []KeyValue `json:"initialNodeLabels"`
|
||||
SshPublicKey *string `json:"sshPublicKey"`
|
||||
QuantityPerSubnet *int `json:"quantityPerSubnet"`
|
||||
SubnetIds []string `json:"subnetIds"`
|
||||
Nodes []Node `json:"nodes"`
|
||||
NodeConfigDetails *NodePoolNodeConfigDetails `json:"nodeConfigDetails"`
|
||||
}{}
|
||||
|
||||
e = json.Unmarshal(data, &model)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
var nn interface{}
|
||||
m.Id = model.Id
|
||||
|
||||
m.CompartmentId = model.CompartmentId
|
||||
|
||||
m.ClusterId = model.ClusterId
|
||||
|
||||
m.Name = model.Name
|
||||
|
||||
m.KubernetesVersion = model.KubernetesVersion
|
||||
|
||||
m.NodeMetadata = model.NodeMetadata
|
||||
|
||||
m.NodeImageId = model.NodeImageId
|
||||
|
||||
m.NodeImageName = model.NodeImageName
|
||||
|
||||
m.NodeShapeConfig = model.NodeShapeConfig
|
||||
|
||||
nn, e = model.NodeSource.UnmarshalPolymorphicJSON(model.NodeSource.JsonData)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
if nn != nil {
|
||||
m.NodeSource = nn.(NodeSourceOption)
|
||||
} else {
|
||||
m.NodeSource = nil
|
||||
}
|
||||
|
||||
nn, e = model.NodeSourceDetails.UnmarshalPolymorphicJSON(model.NodeSourceDetails.JsonData)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
if nn != nil {
|
||||
m.NodeSourceDetails = nn.(NodeSourceDetails)
|
||||
} else {
|
||||
m.NodeSourceDetails = nil
|
||||
}
|
||||
|
||||
m.NodeShape = model.NodeShape
|
||||
|
||||
m.InitialNodeLabels = make([]KeyValue, len(model.InitialNodeLabels))
|
||||
for i, n := range model.InitialNodeLabels {
|
||||
m.InitialNodeLabels[i] = n
|
||||
}
|
||||
|
||||
m.SshPublicKey = model.SshPublicKey
|
||||
|
||||
m.QuantityPerSubnet = model.QuantityPerSubnet
|
||||
|
||||
m.SubnetIds = make([]string, len(model.SubnetIds))
|
||||
for i, n := range model.SubnetIds {
|
||||
m.SubnetIds[i] = n
|
||||
}
|
||||
|
||||
m.Nodes = make([]Node, len(model.Nodes))
|
||||
for i, n := range model.Nodes {
|
||||
m.Nodes[i] = n
|
||||
}
|
||||
|
||||
m.NodeConfigDetails = model.NodeConfigDetails
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodePoolNodeConfigDetails The size and placement configuration of nodes in the node pool.
|
||||
type NodePoolNodeConfigDetails struct {
|
||||
|
||||
// The number of nodes in the node pool.
|
||||
Size *int `mandatory:"false" json:"size"`
|
||||
|
||||
// The OCIDs of the Network Security Group(s) to associate nodes for this node pool with. For more information about NSGs, see NetworkSecurityGroup.
|
||||
NsgIds []string `mandatory:"false" json:"nsgIds"`
|
||||
|
||||
// The placement configurations for the node pool. Provide one placement
|
||||
// configuration for each availability domain in which you intend to launch a node.
|
||||
// To use the node pool with a regional subnet, provide a placement configuration for
|
||||
// each availability domain, and include the regional subnet in each placement
|
||||
// configuration.
|
||||
PlacementConfigs []NodePoolPlacementConfigDetails `mandatory:"false" json:"placementConfigs"`
|
||||
}
|
||||
|
||||
func (m NodePoolNodeConfigDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodePoolOptions Options for creating or updating node pools.
|
||||
type NodePoolOptions struct {
|
||||
|
||||
// Available Kubernetes versions.
|
||||
KubernetesVersions []string `mandatory:"false" json:"kubernetesVersions"`
|
||||
|
||||
// Available shapes for nodes.
|
||||
Shapes []string `mandatory:"false" json:"shapes"`
|
||||
|
||||
// Deprecated. See sources.
|
||||
// When creating a node pool using the `CreateNodePoolDetails` object, only image names contained in this
|
||||
// property can be passed to the `nodeImageName` property.
|
||||
Images []string `mandatory:"false" json:"images"`
|
||||
|
||||
// Available source of the node.
|
||||
Sources []NodeSourceOption `mandatory:"false" json:"sources"`
|
||||
}
|
||||
|
||||
func (m NodePoolOptions) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from json
|
||||
func (m *NodePoolOptions) UnmarshalJSON(data []byte) (e error) {
|
||||
model := struct {
|
||||
KubernetesVersions []string `json:"kubernetesVersions"`
|
||||
Shapes []string `json:"shapes"`
|
||||
Images []string `json:"images"`
|
||||
Sources []nodesourceoption `json:"sources"`
|
||||
}{}
|
||||
|
||||
e = json.Unmarshal(data, &model)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
var nn interface{}
|
||||
m.KubernetesVersions = make([]string, len(model.KubernetesVersions))
|
||||
for i, n := range model.KubernetesVersions {
|
||||
m.KubernetesVersions[i] = n
|
||||
}
|
||||
|
||||
m.Shapes = make([]string, len(model.Shapes))
|
||||
for i, n := range model.Shapes {
|
||||
m.Shapes[i] = n
|
||||
}
|
||||
|
||||
m.Images = make([]string, len(model.Images))
|
||||
for i, n := range model.Images {
|
||||
m.Images[i] = n
|
||||
}
|
||||
|
||||
m.Sources = make([]NodeSourceOption, len(model.Sources))
|
||||
for i, n := range model.Sources {
|
||||
nn, e = n.UnmarshalPolymorphicJSON(n.JsonData)
|
||||
if e != nil {
|
||||
return e
|
||||
}
|
||||
if nn != nil {
|
||||
m.Sources[i] = nn.(NodeSourceOption)
|
||||
} else {
|
||||
m.Sources[i] = nil
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodePoolPlacementConfigDetails The location where a node pool will place nodes.
|
||||
type NodePoolPlacementConfigDetails struct {
|
||||
|
||||
// The availability domain in which to place nodes.
|
||||
// Example: `Uocm:PHX-AD-1`
|
||||
AvailabilityDomain *string `mandatory:"true" json:"availabilityDomain"`
|
||||
|
||||
// The OCID of the subnet in which to place nodes.
|
||||
SubnetId *string `mandatory:"true" json:"subnetId"`
|
||||
}
|
||||
|
||||
func (m NodePoolPlacementConfigDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodePoolSummary The properties that define a node pool summary.
|
||||
type NodePoolSummary struct {
|
||||
|
||||
// The OCID of the node pool.
|
||||
Id *string `mandatory:"false" json:"id"`
|
||||
|
||||
// The OCID of the compartment in which the node pool exists.
|
||||
CompartmentId *string `mandatory:"false" json:"compartmentId"`
|
||||
|
||||
// The OCID of the cluster to which this node pool is attached.
|
||||
ClusterId *string `mandatory:"false" json:"clusterId"`
|
||||
|
||||
// The name of the node pool.
|
||||
Name *string `mandatory:"false" json:"name"`
|
||||
|
||||
// The version of Kubernetes running on the nodes in the node pool.
|
||||
KubernetesVersion *string `mandatory:"false" json:"kubernetesVersion"`
|
||||
|
||||
// Deprecated. see `nodeSource`. The OCID of the image running on the nodes in the node pool.
|
||||
NodeImageId *string `mandatory:"false" json:"nodeImageId"`
|
||||
|
||||
// Deprecated. see `nodeSource`. The name of the image running on the nodes in the node pool.
|
||||
NodeImageName *string `mandatory:"false" json:"nodeImageName"`
|
||||
|
||||
// The shape configuration of the nodes.
|
||||
NodeShapeConfig *NodeShapeConfig `mandatory:"false" json:"nodeShapeConfig"`
|
||||
|
||||
// Deprecated. see `nodeSourceDetails`. Source running on the nodes in the node pool.
|
||||
NodeSource NodeSourceOption `mandatory:"false" json:"nodeSource"`
|
||||
|
||||
// Source running on the nodes in the node pool.
|
||||
NodeSourceDetails NodeSourceDetails `mandatory:"false" json:"nodeSourceDetails"`
|
||||
|
||||
// The name of the node shape of the nodes in the node pool.
|
||||
NodeShape *string `mandatory:"false" json:"nodeShape"`
|
||||
|
||||
// A list of key/value pairs to add to nodes after they join the Kubernetes cluster.
|
||||
InitialNodeLabels []KeyValue `mandatory:"false" json:"initialNodeLabels"`
|
||||
|
||||
// The SSH public key on each node in the node pool on launch.
|
||||
SshPublicKey *string `mandatory:"false" json:"sshPublicKey"`
|
||||
|
||||
// The number of nodes in each subnet.
|
||||
QuantityPerSubnet *int `mandatory:"false" json:"quantityPerSubnet"`
|
||||
|
||||
// The OCIDs of the subnets in which to place nodes for this node pool.
|
||||
SubnetIds []string `mandatory:"false" json:"subnetIds"`
|
||||
|
||||
// The configuration of nodes in the node pool.
|
||||
NodeConfigDetails *NodePoolNodeConfigDetails `mandatory:"false" json:"nodeConfigDetails"`
|
||||
}
|
||||
|
||||
func (m NodePoolSummary) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals from json
|
||||
func (m *NodePoolSummary) UnmarshalJSON(data []byte) (e error) {
|
||||
model := struct {
|
||||
Id *string `json:"id"`
|
||||
CompartmentId *string `json:"compartmentId"`
|
||||
ClusterId *string `json:"clusterId"`
|
||||
Name *string `json:"name"`
|
||||
KubernetesVersion *string `json:"kubernetesVersion"`
|
||||
NodeImageId *string `json:"nodeImageId"`
|
||||
NodeImageName *string `json:"nodeImageName"`
|
||||
NodeShapeConfig *NodeShapeConfig `json:"nodeShapeConfig"`
|
||||
NodeSource nodesourceoption `json:"nodeSource"`
|
||||
NodeSourceDetails nodesourcedetails `json:"nodeSourceDetails"`
|
||||
NodeShape *string `json:"nodeShape"`
|
||||
InitialNodeLabels []KeyValue `json:"initialNodeLabels"`
|
||||
SshPublicKey *string `json:"sshPublicKey"`
|
||||
QuantityPerSubnet *int `json:"quantityPerSubnet"`
|
||||
SubnetIds []string `json:"subnetIds"`
|
||||
NodeConfigDetails *NodePoolNodeConfigDetails `json:"nodeConfigDetails"`
|
||||
}{}
|
||||
|
||||
e = json.Unmarshal(data, &model)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
var nn interface{}
|
||||
m.Id = model.Id
|
||||
|
||||
m.CompartmentId = model.CompartmentId
|
||||
|
||||
m.ClusterId = model.ClusterId
|
||||
|
||||
m.Name = model.Name
|
||||
|
||||
m.KubernetesVersion = model.KubernetesVersion
|
||||
|
||||
m.NodeImageId = model.NodeImageId
|
||||
|
||||
m.NodeImageName = model.NodeImageName
|
||||
|
||||
m.NodeShapeConfig = model.NodeShapeConfig
|
||||
|
||||
nn, e = model.NodeSource.UnmarshalPolymorphicJSON(model.NodeSource.JsonData)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
if nn != nil {
|
||||
m.NodeSource = nn.(NodeSourceOption)
|
||||
} else {
|
||||
m.NodeSource = nil
|
||||
}
|
||||
|
||||
nn, e = model.NodeSourceDetails.UnmarshalPolymorphicJSON(model.NodeSourceDetails.JsonData)
|
||||
if e != nil {
|
||||
return
|
||||
}
|
||||
if nn != nil {
|
||||
m.NodeSourceDetails = nn.(NodeSourceDetails)
|
||||
} else {
|
||||
m.NodeSourceDetails = nil
|
||||
}
|
||||
|
||||
m.NodeShape = model.NodeShape
|
||||
|
||||
m.InitialNodeLabels = make([]KeyValue, len(model.InitialNodeLabels))
|
||||
for i, n := range model.InitialNodeLabels {
|
||||
m.InitialNodeLabels[i] = n
|
||||
}
|
||||
|
||||
m.SshPublicKey = model.SshPublicKey
|
||||
|
||||
m.QuantityPerSubnet = model.QuantityPerSubnet
|
||||
|
||||
m.SubnetIds = make([]string, len(model.SubnetIds))
|
||||
for i, n := range model.SubnetIds {
|
||||
m.SubnetIds[i] = n
|
||||
}
|
||||
|
||||
m.NodeConfigDetails = model.NodeConfigDetails
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodeShapeConfig The shape configuration of the nodes.
|
||||
type NodeShapeConfig struct {
|
||||
|
||||
// The total number of OCPUs available to each node in the node pool.
|
||||
// See here (https://docs.cloud.oracle.com/en-us/iaas/api/#/en/iaas/20160918/Shape/) for details.
|
||||
Ocpus *float32 `mandatory:"false" json:"ocpus"`
|
||||
|
||||
// The total amount of memory available to each node, in gigabytes.
|
||||
MemoryInGBs *float32 `mandatory:"false" json:"memoryInGBs"`
|
||||
}
|
||||
|
||||
func (m NodeShapeConfig) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodeSourceDetails The details of the node's source.
|
||||
type NodeSourceDetails interface {
|
||||
}
|
||||
|
||||
type nodesourcedetails struct {
|
||||
JsonData []byte
|
||||
SourceType string `json:"sourceType"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals json
|
||||
func (m *nodesourcedetails) UnmarshalJSON(data []byte) error {
|
||||
m.JsonData = data
|
||||
type Unmarshalernodesourcedetails nodesourcedetails
|
||||
s := struct {
|
||||
Model Unmarshalernodesourcedetails
|
||||
}{}
|
||||
err := json.Unmarshal(data, &s.Model)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.SourceType = s.Model.SourceType
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UnmarshalPolymorphicJSON unmarshals polymorphic json
|
||||
func (m *nodesourcedetails) UnmarshalPolymorphicJSON(data []byte) (interface{}, error) {
|
||||
|
||||
if data == nil || string(data) == "null" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
switch m.SourceType {
|
||||
case "IMAGE":
|
||||
mm := NodeSourceViaImageDetails{}
|
||||
err = json.Unmarshal(data, &mm)
|
||||
return mm, err
|
||||
default:
|
||||
return *m, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (m nodesourcedetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodeSourceOption The source option for the node.
|
||||
type NodeSourceOption interface {
|
||||
|
||||
// The user-friendly name of the entity corresponding to the OCID.
|
||||
GetSourceName() *string
|
||||
}
|
||||
|
||||
type nodesourceoption struct {
|
||||
JsonData []byte
|
||||
SourceName *string `mandatory:"false" json:"sourceName"`
|
||||
SourceType string `json:"sourceType"`
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals json
|
||||
func (m *nodesourceoption) UnmarshalJSON(data []byte) error {
|
||||
m.JsonData = data
|
||||
type Unmarshalernodesourceoption nodesourceoption
|
||||
s := struct {
|
||||
Model Unmarshalernodesourceoption
|
||||
}{}
|
||||
err := json.Unmarshal(data, &s.Model)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.SourceName = s.Model.SourceName
|
||||
m.SourceType = s.Model.SourceType
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// UnmarshalPolymorphicJSON unmarshals polymorphic json
|
||||
func (m *nodesourceoption) UnmarshalPolymorphicJSON(data []byte) (interface{}, error) {
|
||||
|
||||
if data == nil || string(data) == "null" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var err error
|
||||
switch m.SourceType {
|
||||
case "IMAGE":
|
||||
mm := NodeSourceViaImageOption{}
|
||||
err = json.Unmarshal(data, &mm)
|
||||
return mm, err
|
||||
default:
|
||||
return *m, nil
|
||||
}
|
||||
}
|
||||
|
||||
//GetSourceName returns SourceName
|
||||
func (m nodesourceoption) GetSourceName() *string {
|
||||
return m.SourceName
|
||||
}
|
||||
|
||||
func (m nodesourceoption) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
// NodeSourceTypeEnum Enum with underlying type: string
|
||||
type NodeSourceTypeEnum string
|
||||
|
||||
// Set of constants representing the allowable values for NodeSourceTypeEnum
|
||||
const (
|
||||
NodeSourceTypeImage NodeSourceTypeEnum = "IMAGE"
|
||||
)
|
||||
|
||||
var mappingNodeSourceType = map[string]NodeSourceTypeEnum{
|
||||
"IMAGE": NodeSourceTypeImage,
|
||||
}
|
||||
|
||||
// GetNodeSourceTypeEnumValues Enumerates the set of values for NodeSourceTypeEnum
|
||||
func GetNodeSourceTypeEnumValues() []NodeSourceTypeEnum {
|
||||
values := make([]NodeSourceTypeEnum, 0)
|
||||
for _, v := range mappingNodeSourceType {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodeSourceViaImageDetails Details of the image running on the node.
|
||||
type NodeSourceViaImageDetails struct {
|
||||
|
||||
// The OCID of the image used to boot the node.
|
||||
ImageId *string `mandatory:"true" json:"imageId"`
|
||||
|
||||
// The size of the boot volume in GBs. Minimum value is 50 GB. See here (https://docs.cloud.oracle.com/en-us/iaas/Content/Block/Concepts/bootvolumes.htm) for max custom boot volume sizing and OS-specific requirements.
|
||||
BootVolumeSizeInGBs *int64 `mandatory:"false" json:"bootVolumeSizeInGBs"`
|
||||
}
|
||||
|
||||
func (m NodeSourceViaImageDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// MarshalJSON marshals to json representation
|
||||
func (m NodeSourceViaImageDetails) MarshalJSON() (buff []byte, e error) {
|
||||
type MarshalTypeNodeSourceViaImageDetails NodeSourceViaImageDetails
|
||||
s := struct {
|
||||
DiscriminatorParam string `json:"sourceType"`
|
||||
MarshalTypeNodeSourceViaImageDetails
|
||||
}{
|
||||
"IMAGE",
|
||||
(MarshalTypeNodeSourceViaImageDetails)(m),
|
||||
}
|
||||
|
||||
return json.Marshal(&s)
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// NodeSourceViaImageOption An image can be specified as the source of nodes when launching a node pool using the `nodeSourceDetails` object.
|
||||
type NodeSourceViaImageOption struct {
|
||||
|
||||
// The user-friendly name of the entity corresponding to the OCID.
|
||||
SourceName *string `mandatory:"false" json:"sourceName"`
|
||||
|
||||
// The OCID of the image.
|
||||
ImageId *string `mandatory:"false" json:"imageId"`
|
||||
}
|
||||
|
||||
//GetSourceName returns SourceName
|
||||
func (m NodeSourceViaImageOption) GetSourceName() *string {
|
||||
return m.SourceName
|
||||
}
|
||||
|
||||
func (m NodeSourceViaImageOption) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
|
||||
// MarshalJSON marshals to json representation
|
||||
func (m NodeSourceViaImageOption) MarshalJSON() (buff []byte, e error) {
|
||||
type MarshalTypeNodeSourceViaImageOption NodeSourceViaImageOption
|
||||
s := struct {
|
||||
DiscriminatorParam string `json:"sourceType"`
|
||||
MarshalTypeNodeSourceViaImageOption
|
||||
}{
|
||||
"IMAGE",
|
||||
(MarshalTypeNodeSourceViaImageOption)(m),
|
||||
}
|
||||
|
||||
return json.Marshal(&s)
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
// SortOrderEnum Enum with underlying type: string
|
||||
type SortOrderEnum string
|
||||
|
||||
// Set of constants representing the allowable values for SortOrderEnum
|
||||
const (
|
||||
SortOrderAsc SortOrderEnum = "ASC"
|
||||
SortOrderDesc SortOrderEnum = "DESC"
|
||||
)
|
||||
|
||||
var mappingSortOrder = map[string]SortOrderEnum{
|
||||
"ASC": SortOrderAsc,
|
||||
"DESC": SortOrderDesc,
|
||||
}
|
||||
|
||||
// GetSortOrderEnumValues Enumerates the set of values for SortOrderEnum
|
||||
func GetSortOrderEnumValues() []SortOrderEnum {
|
||||
values := make([]SortOrderEnum, 0)
|
||||
for _, v := range mappingSortOrder {
|
||||
values = append(values, v)
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) 2016, 2018, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
// This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
|
||||
// Code generated. DO NOT EDIT.
|
||||
|
||||
// Container Engine for Kubernetes API
|
||||
//
|
||||
// API for the Container Engine for Kubernetes service. Use this API to build, deploy,
|
||||
// and manage cloud-native applications. For more information, see
|
||||
// Overview of Container Engine for Kubernetes (https://docs.cloud.oracle.com/iaas/Content/ContEng/Concepts/contengoverview.htm).
|
||||
//
|
||||
|
||||
package containerengine
|
||||
|
||||
import (
|
||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/oci-go-sdk/v43/common"
|
||||
)
|
||||
|
||||
// UpdateClusterDetails The properties that define a request to update a cluster.
|
||||
type UpdateClusterDetails struct {
|
||||
|
||||
// The new name for the cluster. Avoid entering confidential information.
|
||||
Name *string `mandatory:"false" json:"name"`
|
||||
|
||||
// The version of Kubernetes to which the cluster masters should be upgraded.
|
||||
KubernetesVersion *string `mandatory:"false" json:"kubernetesVersion"`
|
||||
|
||||
Options *UpdateClusterOptionsDetails `mandatory:"false" json:"options"`
|
||||
|
||||
// The image verification policy for signature validation. Once a policy is created and enabled with
|
||||
// one or more kms keys, the policy will ensure all images deployed has been signed with the key(s)
|
||||
// attached to the policy.
|
||||
ImagePolicyConfig *UpdateImagePolicyConfigDetails `mandatory:"false" json:"imagePolicyConfig"`
|
||||
}
|
||||
|
||||
func (m UpdateClusterDetails) String() string {
|
||||
return common.PointerString(m)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue