1
0
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:
galal-hussein 2018-06-06 19:11:47 +02:00 committed by Alena Prokharchyk
parent 676189a60d
commit 2142661ea7
10 changed files with 323 additions and 55 deletions

28
cloudprovider/aws/aws.go Normal file
View 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
}

View 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
}

View 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
}

View 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
}

View 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
}

View 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)
}

View File

@ -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"
)

View File

@ -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
}

View File

@ -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
View 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 }}
`