mirror of
https://github.com/rancher/rke.git
synced 2025-05-10 09:24:32 +00:00
Refactor cloud provider support
This commit is contained in:
parent
676189a60d
commit
2142661ea7
cloudprovider
cluster
templates
28
cloudprovider/aws/aws.go
Normal file
28
cloudprovider/aws/aws.go
Normal file
@ -0,0 +1,28 @@
|
||||
package aws
|
||||
|
||||
import "github.com/rancher/types/apis/management.cattle.io/v3"
|
||||
|
||||
type CloudProvider struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
const (
|
||||
AWSCloudProviderName = "aws"
|
||||
)
|
||||
|
||||
func GetInstance() *CloudProvider {
|
||||
return &CloudProvider{}
|
||||
}
|
||||
|
||||
func (p *CloudProvider) Init(cloudProviderConfig v3.CloudProvider) error {
|
||||
p.Name = AWSCloudProviderName
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GetName() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GenerateCloudConfigFile() (string, error) {
|
||||
return "", nil
|
||||
}
|
45
cloudprovider/azure/azure.go
Normal file
45
cloudprovider/azure/azure.go
Normal file
@ -0,0 +1,45 @@
|
||||
package azure
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/rancher/types/apis/management.cattle.io/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
AzureCloudProviderName = "azure"
|
||||
)
|
||||
|
||||
type CloudProvider struct {
|
||||
Config *v3.AzureCloudProvider
|
||||
Name string
|
||||
}
|
||||
|
||||
func GetInstance() *CloudProvider {
|
||||
return &CloudProvider{}
|
||||
}
|
||||
|
||||
func (p *CloudProvider) Init(cloudProviderConfig v3.CloudProvider) error {
|
||||
if cloudProviderConfig.AzureCloudProvider == nil {
|
||||
return fmt.Errorf("Azure Cloud Provider Config is empty")
|
||||
}
|
||||
p.Name = AzureCloudProviderName
|
||||
if cloudProviderConfig.Name != "" {
|
||||
p.Name = cloudProviderConfig.Name
|
||||
}
|
||||
p.Config = cloudProviderConfig.AzureCloudProvider
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GetName() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GenerateCloudConfigFile() (string, error) {
|
||||
cloudConfig, err := json.MarshalIndent(p.Config, "", "\n")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(cloudConfig), nil
|
||||
}
|
42
cloudprovider/cloudprovider.go
Normal file
42
cloudprovider/cloudprovider.go
Normal file
@ -0,0 +1,42 @@
|
||||
package cloudprovider
|
||||
|
||||
import (
|
||||
"github.com/rancher/rke/cloudprovider/aws"
|
||||
"github.com/rancher/rke/cloudprovider/azure"
|
||||
"github.com/rancher/rke/cloudprovider/custom"
|
||||
"github.com/rancher/rke/cloudprovider/openstack"
|
||||
"github.com/rancher/rke/cloudprovider/vsphere"
|
||||
"github.com/rancher/types/apis/management.cattle.io/v3"
|
||||
)
|
||||
|
||||
type CloudProvider interface {
|
||||
Init(cloudProviderConfig v3.CloudProvider) error
|
||||
GenerateCloudConfigFile() (string, error)
|
||||
GetName() string
|
||||
}
|
||||
|
||||
func InitCloudProvider(cloudProviderConfig v3.CloudProvider) (CloudProvider, error) {
|
||||
var p CloudProvider
|
||||
if cloudProviderConfig.Name == aws.AWSCloudProviderName {
|
||||
p = aws.GetInstance()
|
||||
}
|
||||
if cloudProviderConfig.AzureCloudProvider != nil || cloudProviderConfig.Name == azure.AzureCloudProviderName {
|
||||
p = azure.GetInstance()
|
||||
}
|
||||
if cloudProviderConfig.OpenstackCloudProvider != nil || cloudProviderConfig.Name == openstack.OpenstackCloudProviderName {
|
||||
p = openstack.GetInstance()
|
||||
}
|
||||
if cloudProviderConfig.VsphereCloudProvider != nil || cloudProviderConfig.Name == vsphere.VsphereCloudProviderName {
|
||||
p = vsphere.GetInstance()
|
||||
}
|
||||
if cloudProviderConfig.CustomCloudProvider != "" {
|
||||
p = custom.GetInstance()
|
||||
}
|
||||
|
||||
if p != nil {
|
||||
if err := p.Init(cloudProviderConfig); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
26
cloudprovider/custom/custom.go
Normal file
26
cloudprovider/custom/custom.go
Normal file
@ -0,0 +1,26 @@
|
||||
package custom
|
||||
|
||||
import "github.com/rancher/types/apis/management.cattle.io/v3"
|
||||
|
||||
type CloudProvider struct {
|
||||
Name string
|
||||
Config string
|
||||
}
|
||||
|
||||
func GetInstance() *CloudProvider {
|
||||
return &CloudProvider{}
|
||||
}
|
||||
|
||||
func (p *CloudProvider) Init(cloudProviderConfig v3.CloudProvider) error {
|
||||
p.Name = cloudProviderConfig.Name
|
||||
p.Config = cloudProviderConfig.CustomCloudProvider
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GetName() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GenerateCloudConfigFile() (string, error) {
|
||||
return p.Config, nil
|
||||
}
|
51
cloudprovider/openstack/openstack.go
Normal file
51
cloudprovider/openstack/openstack.go
Normal file
@ -0,0 +1,51 @@
|
||||
package openstack
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-ini/ini"
|
||||
"github.com/rancher/types/apis/management.cattle.io/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
OpenstackCloudProviderName = "openstack"
|
||||
)
|
||||
|
||||
type CloudProvider struct {
|
||||
Config *v3.OpenstackCloudProvider
|
||||
Name string
|
||||
}
|
||||
|
||||
func GetInstance() *CloudProvider {
|
||||
return &CloudProvider{}
|
||||
}
|
||||
|
||||
func (p *CloudProvider) Init(cloudProviderConfig v3.CloudProvider) error {
|
||||
if cloudProviderConfig.OpenstackCloudProvider == nil {
|
||||
return fmt.Errorf("Openstack Cloud Provider Config is empty")
|
||||
}
|
||||
p.Name = OpenstackCloudProviderName
|
||||
if cloudProviderConfig.Name != "" {
|
||||
p.Name = cloudProviderConfig.Name
|
||||
}
|
||||
p.Config = cloudProviderConfig.OpenstackCloudProvider
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GetName() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GenerateCloudConfigFile() (string, error) {
|
||||
// Generate INI style configuration
|
||||
buf := new(bytes.Buffer)
|
||||
cloudConfig := ini.Empty()
|
||||
if err := ini.ReflectFrom(cloudConfig, p.Config); err != nil {
|
||||
return "", fmt.Errorf("Failed to parse Openstack cloud config")
|
||||
}
|
||||
if _, err := cloudConfig.WriteTo(buf); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
46
cloudprovider/vsphere/vsphere.go
Normal file
46
cloudprovider/vsphere/vsphere.go
Normal file
@ -0,0 +1,46 @@
|
||||
package vsphere
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rancher/rke/templates"
|
||||
"github.com/rancher/types/apis/management.cattle.io/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
VsphereCloudProviderName = "vsphere"
|
||||
VsphereConfig = "VsphereConfig"
|
||||
)
|
||||
|
||||
type CloudProvider struct {
|
||||
Config *v3.VsphereCloudProvider
|
||||
Name string
|
||||
}
|
||||
|
||||
func GetInstance() *CloudProvider {
|
||||
return &CloudProvider{}
|
||||
}
|
||||
|
||||
func (p *CloudProvider) Init(cloudProviderConfig v3.CloudProvider) error {
|
||||
if cloudProviderConfig.VsphereCloudProvider == nil {
|
||||
return fmt.Errorf("Vsphere Cloud Provider Config is empty")
|
||||
}
|
||||
p.Name = VsphereCloudProviderName
|
||||
if cloudProviderConfig.Name != "" {
|
||||
p.Name = cloudProviderConfig.Name
|
||||
}
|
||||
p.Config = cloudProviderConfig.VsphereCloudProvider
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GetName() string {
|
||||
return p.Name
|
||||
}
|
||||
|
||||
func (p *CloudProvider) GenerateCloudConfigFile() (string, error) {
|
||||
// Generate INI style configuration from template https://github.com/go-ini/ini/issues/84
|
||||
VsphereConfig := map[string]v3.VsphereCloudProvider{
|
||||
VsphereConfig: *p.Config,
|
||||
}
|
||||
return templates.CompileTemplateFromMap(templates.VsphereCloudProviderTemplate, VsphereConfig)
|
||||
}
|
@ -16,7 +16,7 @@ import (
|
||||
const (
|
||||
CloudConfigDeployer = "cloud-config-deployer"
|
||||
CloudConfigServiceName = "cloud"
|
||||
CloudConfigPath = "/etc/kubernetes/cloud-config.json"
|
||||
CloudConfigPath = "/etc/kubernetes/cloud-config"
|
||||
CloudConfigEnv = "RKE_CLOUD_CONFIG"
|
||||
)
|
||||
|
||||
|
@ -2,13 +2,12 @@ package cluster
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/rancher/rke/authz"
|
||||
"github.com/rancher/rke/cloudprovider"
|
||||
"github.com/rancher/rke/docker"
|
||||
"github.com/rancher/rke/hosts"
|
||||
"github.com/rancher/rke/k8s"
|
||||
@ -59,8 +58,6 @@ const (
|
||||
LocalNodeHostname = "localhost"
|
||||
LocalNodeUser = "root"
|
||||
CloudProvider = "CloudProvider"
|
||||
AzureCloudProvider = "azure"
|
||||
AWSCloudProvider = "aws"
|
||||
ControlPlane = "controlPlane"
|
||||
WorkerPlane = "workerPlan"
|
||||
EtcdPlane = "etcd"
|
||||
@ -180,11 +177,22 @@ func ParseCluster(
|
||||
}
|
||||
c.PrivateRegistriesMap[pr.URL] = pr
|
||||
}
|
||||
// parse the cluster config file
|
||||
c.CloudConfigFile, err = c.parseCloudConfig(ctx)
|
||||
// Get Cloud Provider
|
||||
p, err := cloudprovider.InitCloudProvider(c.CloudProvider)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse cloud config file: %v", err)
|
||||
return nil, fmt.Errorf("Failed to initialize cloud provider: %v", err)
|
||||
}
|
||||
if p != nil {
|
||||
c.CloudConfigFile, err = p.GenerateCloudConfigFile()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to parse cloud config file: %v", err)
|
||||
}
|
||||
c.CloudProvider.Name = p.GetName()
|
||||
if c.CloudProvider.Name == "" {
|
||||
return nil, fmt.Errorf("Name of the cloud provider is not defined for custom provider")
|
||||
}
|
||||
}
|
||||
|
||||
// Create k8s wrap transport for bastion host
|
||||
if len(c.BastionHost.Address) > 0 {
|
||||
c.K8sWrapTransport = hosts.BastionHostWrapTransport(c.BastionHost)
|
||||
@ -371,47 +379,3 @@ func ConfigureCluster(
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cluster) parseCloudConfig(ctx context.Context) (string, error) {
|
||||
// check for azure cloud provider
|
||||
if c.CloudProvider.AzureCloudProvider != nil {
|
||||
c.CloudProvider.Name = AzureCloudProvider
|
||||
jsonString, err := json.MarshalIndent(c.CloudProvider.AzureCloudProvider, "", "\n")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(jsonString), nil
|
||||
}
|
||||
if c.CloudProvider.AWSCloudProvider != nil {
|
||||
c.CloudProvider.Name = AWSCloudProvider
|
||||
return "", nil
|
||||
}
|
||||
if len(c.CloudProvider.CloudConfig) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
// handle generic cloud config
|
||||
tmpMap := make(map[string]interface{})
|
||||
for key, value := range c.CloudProvider.CloudConfig {
|
||||
tmpBool, err := strconv.ParseBool(value)
|
||||
if err == nil {
|
||||
tmpMap[key] = tmpBool
|
||||
continue
|
||||
}
|
||||
tmpInt, err := strconv.ParseInt(value, 10, 64)
|
||||
if err == nil {
|
||||
tmpMap[key] = tmpInt
|
||||
continue
|
||||
}
|
||||
tmpFloat, err := strconv.ParseFloat(value, 64)
|
||||
if err == nil {
|
||||
tmpMap[key] = tmpFloat
|
||||
continue
|
||||
}
|
||||
tmpMap[key] = value
|
||||
}
|
||||
jsonString, err := json.MarshalIndent(tmpMap, "", "\n")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(jsonString), nil
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
|
||||
ref "github.com/docker/distribution/reference"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/rancher/rke/cloudprovider/aws"
|
||||
"github.com/rancher/rke/docker"
|
||||
"github.com/rancher/rke/hosts"
|
||||
"github.com/rancher/rke/k8s"
|
||||
@ -129,7 +130,7 @@ func (c *Cluster) BuildKubeAPIProcess(prefixPath string) v3.Process {
|
||||
"service-account-key-file": pki.GetKeyPath(pki.KubeAPICertName),
|
||||
"apiserver-count": strconv.Itoa(apiserverCount),
|
||||
}
|
||||
if len(c.CloudProvider.Name) > 0 && c.CloudProvider.Name != AWSCloudProvider {
|
||||
if len(c.CloudProvider.Name) > 0 && c.CloudProvider.Name != aws.AWSCloudProviderName {
|
||||
CommandArgs["cloud-config"] = CloudConfigPath
|
||||
}
|
||||
// check if our version has specific options for this component
|
||||
@ -222,7 +223,7 @@ func (c *Cluster) BuildKubeControllerProcess(prefixPath string) v3.Process {
|
||||
"service-account-private-key-file": pki.GetKeyPath(pki.KubeAPICertName),
|
||||
"root-ca-file": pki.GetCertPath(pki.CACertName),
|
||||
}
|
||||
if len(c.CloudProvider.Name) > 0 && c.CloudProvider.Name != AWSCloudProvider {
|
||||
if len(c.CloudProvider.Name) > 0 && c.CloudProvider.Name != aws.AWSCloudProviderName {
|
||||
CommandArgs["cloud-config"] = CloudConfigPath
|
||||
}
|
||||
|
||||
@ -314,7 +315,7 @@ func (c *Cluster) BuildKubeletProcess(host *hosts.Host, prefixPath string) v3.Pr
|
||||
if host.Address != host.InternalAddress {
|
||||
CommandArgs["node-ip"] = host.InternalAddress
|
||||
}
|
||||
if len(c.CloudProvider.Name) > 0 && c.CloudProvider.Name != AWSCloudProvider {
|
||||
if len(c.CloudProvider.Name) > 0 && c.CloudProvider.Name != aws.AWSCloudProviderName {
|
||||
CommandArgs["cloud-config"] = CloudConfigPath
|
||||
}
|
||||
|
||||
|
65
templates/vsphere.go
Normal file
65
templates/vsphere.go
Normal file
@ -0,0 +1,65 @@
|
||||
package templates
|
||||
|
||||
const VsphereCloudProviderTemplate = `
|
||||
[Global]
|
||||
user = "{{ .VsphereConfig.Global.User }}"
|
||||
password = "{{ .VsphereConfig.Global.Password }}"
|
||||
{{- if ne .VsphereConfig.Global.VCenterIP "" }}
|
||||
server = "{{ .VsphereConfig.Global.VCenterIP }}"
|
||||
{{- end }}
|
||||
{{- if ne .VsphereConfig.Global.VCenterPort "" }}
|
||||
port = "{{ .VsphereConfig.Global.VCenterPort }}"
|
||||
{{- end }}
|
||||
insecure-flag = "{{ .VsphereConfig.Global.InsecureFlag }}"
|
||||
{{- if ne .VsphereConfig.Global.Datacenters "" }}
|
||||
datacenters = "{{ .VsphereConfig.Global.Datacenters }}"
|
||||
{{- end }}
|
||||
{{- if ne .VsphereConfig.Global.Datacenter "" }}
|
||||
datacenter = "{{ .VsphereConfig.Global.Datacenter }}"
|
||||
{{- end }}
|
||||
{{- if ne .VsphereConfig.Global.DefaultDatastore "" }}
|
||||
datastore = "{{ .VsphereConfig.Global.DefaultDatastore }}"
|
||||
{{- end }}
|
||||
{{- if ne .VsphereConfig.Global.WorkingDir "" }}
|
||||
working-dir = "{{ .VsphereConfig.Global.WorkingDir }}"
|
||||
{{- end }}
|
||||
soap-roundtrip-count = "{{ .VsphereConfig.Global.RoundTripperCount }}"
|
||||
{{- if ne .VsphereConfig.Global.VMUUID "" }}
|
||||
vm-uuid = "{{ .VsphereConfig.Global.VMUUID }}"
|
||||
{{- end }}
|
||||
{{- if ne .VsphereConfig.Global.VMName "" }}
|
||||
vm-name = "{{ .VsphereConfig.Global.VMName }}"
|
||||
{{- end }}
|
||||
|
||||
{{ range $k,$v := .VsphereConfig.VirtualCenter }}
|
||||
[VirtualCenter "{{ $k }}"]
|
||||
user = "{{ $v.User }}"
|
||||
password = "{{ $v.Password }}"
|
||||
{{- if ne $v.VCenterPort "" }}
|
||||
port = "{{ $v.VCenterPort }}"
|
||||
{{- end }}
|
||||
{{- if ne $v.Datacenters "" }}
|
||||
datacenters = "{{ $v.Datacenters }}"
|
||||
{{- end }}
|
||||
{{- if ne $v.Datacenters "" }}
|
||||
soap-roundtrip-count = "{{ $v.Datacenters }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
[Workspace]
|
||||
server = "{{ .VsphereConfig.Workspace.VCenterIP }}"
|
||||
datacenter = "{{ .VsphereConfig.Workspace.Datacenter }}"
|
||||
folder = "{{ .VsphereConfig.Workspace.Folder }}"
|
||||
default-datastore = "{{ .VsphereConfig.Workspace.DefaultDatastore }}"
|
||||
resourcepool-path = "{{ .VsphereConfig.Workspace.ResourcePoolPath }}"
|
||||
|
||||
[Disk]
|
||||
{{- if ne .VsphereConfig.Disk.SCSIControllerType "" }}
|
||||
scsicontrollertype = {{ .VsphereConfig.Disk.SCSIControllerType }}
|
||||
{{- end }}
|
||||
|
||||
[Network]
|
||||
{{- if ne .VsphereConfig.Network.PublicNetwork "" }}
|
||||
public-network = "{{ .VsphereConfig.Network.PublicNetwork }}"
|
||||
{{- end }}
|
||||
`
|
Loading…
Reference in New Issue
Block a user