Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug 1824426: Allow to define primary ip address for machines #88

Merged
merged 1 commit into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 9 additions & 73 deletions pkg/cloud/openstack/clients/machineservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,8 @@ limitations under the License.
package clients

import (
"crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
"net/http"
"time"

"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
Expand Down Expand Up @@ -155,33 +152,12 @@ func GetCloudFromSecret(kubeClient kubernetes.Interface, namespace string, secre

// TODO: Eventually we'll have a NewInstanceServiceFromCluster too
func NewInstanceServiceFromMachine(kubeClient kubernetes.Interface, machine *machinev1.Machine) (*InstanceService, error) {
machineSpec, err := openstackconfigv1.MachineSpecFromProviderSpec(machine.Spec.ProviderSpec)
cloud, err := GetCloud(kubeClient, machine)
if err != nil {
return nil, fmt.Errorf("Failed to get Machine Spec from Provider Spec: %v", err)
}
cloud := clientconfig.Cloud{}
if machineSpec.CloudsSecret != nil && machineSpec.CloudsSecret.Name != "" {
namespace := machineSpec.CloudsSecret.Namespace
if namespace == "" {
namespace = machine.Namespace
}
cloud, err = GetCloudFromSecret(kubeClient, namespace, machineSpec.CloudsSecret.Name, machineSpec.CloudName)
if err != nil {
return nil, fmt.Errorf("Failed to get cloud from secret: %v", err)
}
}

cloudConfig, err := kubeClient.CoreV1().ConfigMaps("openshift-config").Get("cloud-provider-config", metav1.GetOptions{})
if err != nil {
klog.Warningf("failed to get configmap openshift-config/cloud-provider-config from kubernetes api: %v", err)
return NewInstanceServiceFromCloud(cloud, nil)
}

if cacert, ok := cloudConfig.Data["ca-bundle.pem"]; ok {
return NewInstanceServiceFromCloud(cloud, []byte(cacert))
return nil, err
}

return NewInstanceServiceFromCloud(cloud, nil)
return NewInstanceServiceFromCloud(cloud, GetCACertificate(kubeClient))
}

func NewInstanceService() (*InstanceService, error) {
Expand All @@ -190,81 +166,41 @@ func NewInstanceService() (*InstanceService, error) {
}

func NewInstanceServiceFromCloud(cloud clientconfig.Cloud, cert []byte) (*InstanceService, error) {
clientOpts := new(clientconfig.ClientOpts)

if cloud.AuthInfo != nil {
clientOpts.AuthInfo = cloud.AuthInfo
clientOpts.AuthType = cloud.AuthType
clientOpts.Cloud = cloud.Cloud
clientOpts.RegionName = cloud.RegionName
}

opts, err := clientconfig.AuthOptions(clientOpts)

provider, err := GetProviderClient(cloud, cert)
if err != nil {
return nil, err
}

opts.AllowReauth = true

provider, err := openstack.NewClient(opts.IdentityEndpoint)
if err != nil {
return nil, fmt.Errorf("Create new provider client failed: %v", err)
}

if cert != nil {
certPool, err := x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("Create system cert pool failed: %v", err)
}
certPool.AppendCertsFromPEM(cert)
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
},
}
provider.HTTPClient = client
} else {
klog.Infof("Cloud provider CA cert not provided, using system trust bundle")
}

err = openstack.Authenticate(provider, *opts)
if err != nil {
return nil, fmt.Errorf("Failed to authenticate provider client: %v", err)
}

identityClient, err := openstack.NewIdentityV3(provider, gophercloud.EndpointOpts{
Region: "",
})
if err != nil {
return nil, fmt.Errorf("Create identityClient err: %v", err)
}
serverClient, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{
Region: clientOpts.RegionName,
Region: cloud.RegionName,
})

if err != nil {
return nil, fmt.Errorf("Create serviceClient err: %v", err)
}

networkingClient, err := openstack.NewNetworkV2(provider, gophercloud.EndpointOpts{
Region: clientOpts.RegionName,
Region: cloud.RegionName,
})
if err != nil {
return nil, fmt.Errorf("Create networkingClient err: %v", err)
}

imagesClient, err := openstack.NewImageServiceV2(provider, gophercloud.EndpointOpts{
Region: clientOpts.RegionName,
Region: cloud.RegionName,
})
if err != nil {
return nil, fmt.Errorf("Create ImageClient err: %v", err)
}

volumeClient, err := openstack.NewBlockStorageV3(provider, gophercloud.EndpointOpts{
Region: clientOpts.RegionName,
Region: cloud.RegionName,
})
if err != nil {
return nil, fmt.Errorf("Create VolumeClient err: %v", err)
Expand All @@ -277,7 +213,7 @@ func NewInstanceServiceFromCloud(cloud clientconfig.Cloud, cert []byte) (*Instan
networkClient: networkingClient,
imagesClient: imagesClient,
volumeClient: volumeClient,
regionName: clientOpts.RegionName,
regionName: cloud.RegionName,
}, nil
}

Expand Down
107 changes: 107 additions & 0 deletions pkg/cloud/openstack/clients/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package clients

import (
"crypto/tls"
"crypto/x509"
"fmt"
"net/http"

"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack"
"github.com/gophercloud/utils/openstack/clientconfig"
machinev1 "github.com/openshift/cluster-api/pkg/apis/machine/v1beta1"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/klog"
openstackconfigv1 "sigs.k8s.io/cluster-api-provider-openstack/pkg/apis/openstackproviderconfig/v1alpha1"
)

// GetCloud fetches cloud credentials from a secret and return a parsed Cloud structure
func GetCloud(kubeClient kubernetes.Interface, machine *machinev1.Machine) (clientconfig.Cloud, error) {
cloud := clientconfig.Cloud{}
machineSpec, err := openstackconfigv1.MachineSpecFromProviderSpec(machine.Spec.ProviderSpec)
if err != nil {
return cloud, fmt.Errorf("Failed to get Machine Spec from Provider Spec: %v", err)
}

if machineSpec.CloudsSecret == nil || machineSpec.CloudsSecret.Name == "" {
return cloud, fmt.Errorf("Cloud secret name can't be empty")
}

namespace := machineSpec.CloudsSecret.Namespace
if namespace == "" {
namespace = machine.Namespace
}
cloud, err = GetCloudFromSecret(kubeClient, namespace, machineSpec.CloudsSecret.Name, machineSpec.CloudName)
if err != nil {
return cloud, fmt.Errorf("Failed to get cloud from secret: %v", err)
}

return cloud, nil
}

// GetCACertificate gets the CA certificate from the configmap
func GetCACertificate(kubeClient kubernetes.Interface) []byte {
cloudConfig, err := kubeClient.CoreV1().ConfigMaps("openshift-config").Get("cloud-provider-config", metav1.GetOptions{})
if err != nil {
klog.Warningf("failed to get configmap openshift-config/cloud-provider-config from kubernetes api: %v", err)
return nil
}

if cacert, ok := cloudConfig.Data["ca-bundle.pem"]; ok {
return []byte(cacert)
}

return nil
}

// GetProviderClient returns an authenticated provider client based on values in the cloud structure
func GetProviderClient(cloud clientconfig.Cloud, cert []byte) (*gophercloud.ProviderClient, error) {
clientOpts := new(clientconfig.ClientOpts)

if cloud.AuthInfo != nil {
clientOpts.AuthInfo = cloud.AuthInfo
clientOpts.AuthType = cloud.AuthType
clientOpts.Cloud = cloud.Cloud
clientOpts.RegionName = cloud.RegionName
}

opts, err := clientconfig.AuthOptions(clientOpts)

if err != nil {
return nil, err
}

opts.AllowReauth = true

provider, err := openstack.NewClient(opts.IdentityEndpoint)
if err != nil {
return nil, fmt.Errorf("Create new provider client failed: %v", err)
}

if cert != nil {
certPool, err := x509.SystemCertPool()
if err != nil {
return nil, fmt.Errorf("Create system cert pool failed: %v", err)
}
certPool.AppendCertsFromPEM(cert)
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
},
},
}
provider.HTTPClient = client
} else {
klog.Infof("Cloud provider CA cert not provided, using system trust bundle")
}

err = openstack.Authenticate(provider, *opts)
if err != nil {
return nil, fmt.Errorf("Failed to authenticate provider client: %v", err)
}

return provider, nil
}
Loading