Skip to content

Commit

Permalink
Merge pull request #10 from gsrajpal/dedicated-host-feature
Browse files Browse the repository at this point in the history
Dedicated host feature
  • Loading branch information
openshift-merge-robot committed Oct 8, 2021
2 parents c0f28b1 + 38e3607 commit 4d7907a
Show file tree
Hide file tree
Showing 31 changed files with 4,805 additions and 253 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ require (
github.com/IBM/vpc-go-sdk v0.6.0
github.com/blang/semver v3.5.1+incompatible
github.com/go-logr/logr v0.4.0
github.com/golang-jwt/jwt v3.2.2+incompatible
github.com/golang/mock v1.4.4
github.com/onsi/ginkgo v1.15.0
github.com/onsi/gomega v1.10.5
github.com/openshift/api v0.0.0-20210416115537-a60c0dc032fd
github.com/openshift/machine-api-operator v0.2.1-0.20210504014029-a132ec00f7dd

github.com/pkg/errors v0.9.1
k8s.io/api v0.21.0
k8s.io/apimachinery v0.21.1
k8s.io/client-go v0.21.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
Expand Down
90 changes: 84 additions & 6 deletions pkg/actuators/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/IBM/go-sdk-core/v5/core"
"github.com/IBM/platform-services-go-sdk/resourcemanagerv2"
"github.com/IBM/vpc-go-sdk/vpcv1"
"github.com/golang-jwt/jwt"
ibmcloudproviderv1 "github.com/openshift/cluster-api-provider-ibmcloud/pkg/apis/ibmcloudprovider/v1beta1"
"github.com/pkg/errors"
)
Expand All @@ -45,10 +46,12 @@ type Client interface {
GetResourceGroupIDByName(resourceGroupName string) (string, error)
GetSubnetIDbyName(subnetName string, resourceGroupID string) (string, error)
GetSecurityGroupsByName(securityGroupNames []string, resourceGroupID string, vpcID string) ([]vpcv1.SecurityGroupIdentityIntf, error)
GetDedicatedHostByName(dedicatedHostName string, resourceGroupID string, zoneName string) (string, error)
}

// ibmCloudClient makes call to IBM Cloud APIs
type ibmCloudClient struct {
AccountID string
vpcService *vpcv1.VpcV1
resourceManagerService *resourcemanagerv2.ResourceManagerV2
}
Expand All @@ -59,11 +62,40 @@ type IbmcloudClientBuilderFuncType func(credentialVal string, providerSpec ibmcl
// NewClient initilizes a new validated client
func NewClient(credentialVal string, providerSpec ibmcloudproviderv1.IBMCloudMachineProviderSpec) (Client, error) {

// authenticator
// Authenticator
authenticator := &core.IamAuthenticator{
ApiKey: credentialVal,
}

// Retrieve IAM Token
iamToken, err := authenticator.RequestToken()
if err != nil {
return nil, err
}

// Parse access token retrieved from IAM
// Ignore "no Keyfunc was provided" error - we only want to extract the account id
// The token will not be used to perform any further actions
token, _ := jwt.Parse(iamToken.AccessToken, nil)

// Extract account ID
var accountID string
if claimsObj, ok := token.Claims.(jwt.MapClaims); ok {
// Check if account key is present
if accountObj, ok := claimsObj["account"].(map[string]interface{}); ok {
// Check if bss key is present
if bss, ok := accountObj["bss"].(string); ok {
// set accountID
accountID = bss
}
}
}

// Check accountID
if accountID == "" {
return nil, fmt.Errorf("could not parse account id from token")
}

// IC Virtual Private Cloud (VPC) API
vpcService, err := vpcv1.NewVpcV1(&vpcv1.VpcV1Options{
Authenticator: authenticator,
Expand Down Expand Up @@ -94,6 +126,7 @@ func NewClient(credentialVal string, providerSpec ibmcloudproviderv1.IBMCloudMac
}

return &ibmCloudClient{
AccountID: accountID,
vpcService: vpcService,
resourceManagerService: resourceManagerService,
}, nil
Expand Down Expand Up @@ -254,11 +287,8 @@ func (c *ibmCloudClient) InstanceCreate(machineName string, machineProviderConfi
return nil, err
}

// Create Instance Options
options := &vpcv1.CreateInstanceOptions{}

// Set Instance Prototype - Contains all the info necessary to provision an instance
options.SetInstancePrototype(&vpcv1.InstancePrototype{
instancePrototypeObj := &vpcv1.InstancePrototype{
Name: &machineName,
Image: &vpcv1.ImageIdentity{
ID: &imageID,
Expand All @@ -282,7 +312,24 @@ func (c *ibmCloudClient) InstanceCreate(machineName string, machineProviderConfi
ID: &vpcID,
},
UserData: &userData,
})
}

// Get Dedicated Host ID if needed
if machineProviderConfig.DedicatedHost != "" {
dedicatedHostID, err := c.GetDedicatedHostByName(machineProviderConfig.DedicatedHost, resourceGroupID, machineProviderConfig.Zone)
if err != nil {
return nil, err
}
instancePrototypeObj.PlacementTarget = &vpcv1.InstancePlacementTargetPrototypeDedicatedHostIdentity{
ID: &dedicatedHostID,
}
}

// Create Instance Options
options := &vpcv1.CreateInstanceOptions{}

// Ser Instance Prototype
options.SetInstancePrototype(instancePrototypeObj)

// Create a new Instance from an instance prototype object
instance, _, err := c.vpcService.CreateInstance(options)
Expand Down Expand Up @@ -350,6 +397,8 @@ func (c *ibmCloudClient) GetResourceGroupIDByName(resourceGroupName string) (str
resourceGroupOptions := c.resourceManagerService.NewListResourceGroupsOptions()
// Set Resource Group Name
resourceGroupOptions.SetName(resourceGroupName)
// Set Account ID
resourceGroupOptions.SetAccountID(c.AccountID)
// Get Resource Group
resourceGroup, _, err := c.resourceManagerService.ListResourceGroups(resourceGroupOptions)
if err != nil {
Expand Down Expand Up @@ -432,3 +481,32 @@ func (c *ibmCloudClient) GetSecurityGroupsByName(securityGroupNames []string, re
return nil, fmt.Errorf("could not retrieve security group ids of names: %v", securityGroupMap)

}

// GetDedicatedHostByName retrieves Dedicated Hosts info
func (c *ibmCloudClient) GetDedicatedHostByName(dedicatedHostName string, resourceGroupID string, zoneName string) (string, error) {
// Initialize List Dedicated Hosts Options
dedicatedHostOptions := c.vpcService.NewListDedicatedHostsOptions()

// Set Resource Group ID
dedicatedHostOptions.SetResourceGroupID(resourceGroupID)

// Set Zone
dedicatedHostOptions.SetZoneName(zoneName)

// Get a list of all Dedicated Hosts
dedicatedHosts, _, err := c.vpcService.ListDedicatedHosts(dedicatedHostOptions)
if err != nil {
return "", err
}

if dedicatedHosts != nil && len(dedicatedHosts.DedicatedHosts) > 0 {
for _, eachDedicatedHost := range dedicatedHosts.DedicatedHosts {
if *eachDedicatedHost.Name == dedicatedHostName {
// return Dedicated Host ID
return *eachDedicatedHost.ID, nil
}
}
}

return "", fmt.Errorf("could not retrieve dedicated host id of name: %v", dedicatedHostName)
}
15 changes: 15 additions & 0 deletions pkg/actuators/client/mock/client_mock_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ type IBMCloudMachineProviderSpec struct {
// Example: bx2-8x32 (8 vCPUs, 32 GB RAM)
Profile string `json:"profile"`

// A DedicatedHost is the name of the underlying provisioned host in your VPC on which the instance/s
// will be created with the defined Profile.
// A dedicated host provides a single tenancy ensuring only your Compute/VSI's are provisioned on it.
// Instances provisioned on a dedicated host adds another layer of protection while minimizing latency
// and maximizing performance between the instances provisioned on a single host.
DedicatedHost string `json:"dedicatedHost,omitempty"`

// Region of the virtual machine
Region string `json:"region"`

Expand Down
14 changes: 8 additions & 6 deletions pkg/apis/ibmcloudprovider/v1beta1/register_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ import (

var (
expectedProviderSpec = IBMCloudMachineProviderSpec{
VPC: "test-vpc",
Image: "test-instance-image",
Profile: "bx2d-32x128",
Zone: "us-east-1",
Region: "us-east",
VPC: "test-vpc",
Image: "test-instance-image",
Profile: "bx2d-32x128",
DedicatedHost: "dedicated-host-name",
Zone: "us-east-1",
Region: "us-east",
ResourceGroup: "aaab-bbbc-cccd-zzzz-xxxx",
UserDataSecret: &corev1.LocalObjectReference{
Name: "userData",
},
Expand All @@ -45,7 +47,7 @@ var (
},
},
}
expectedRawProviderSpec = `{"metadata":{"creationTimestamp":null},"vpc":"test-vpc","image":"test-instance-image","profile":"bx2d-32x128","region":"us-east","zone":"us-east-1","resourceGroup":"","primaryNetworkInterface":{"subnet":"test-subnet","securityGroups":["test-security-group-1","test-security-group-2"]},"userDataSecret":{"name":"userData"},"credentialsSecret":{"name":"credentialKey"}}`
expectedRawProviderSpec = `{"metadata":{"creationTimestamp":null},"vpc":"test-vpc","image":"test-instance-image","profile":"bx2d-32x128","dedicatedHost":"dedicated-host-name","region":"us-east","zone":"us-east-1","resourceGroup":"aaab-bbbc-cccd-zzzz-xxxx","primaryNetworkInterface":{"subnet":"test-subnet","securityGroups":["test-security-group-1","test-security-group-2"]},"userDataSecret":{"name":"userData"},"credentialsSecret":{"name":"credentialKey"}}`

instanceID = "test-instance-id"
instanceState = "running"
Expand Down

0 comments on commit 4d7907a

Please sign in to comment.