Skip to content

Commit

Permalink
Add gcp provider support
Browse files Browse the repository at this point in the history
```
$ crc-cloud create gcp --gcp-image-id crc --backed-url file:///tmp/gcp/ --project-name prkumar-test --output /tmp/gcp --key-filepath /home/prkumar/.crc/cache/crc_libvirt_4.13.6_amd64/id_ecdsa_crc --pullsecret-filepath /home/prkumar/pull-secret  --gcp-disk-size 100 --gcp-instance-type n1-standard-8
```
  • Loading branch information
praveenkumar committed Sep 15, 2023
1 parent beb9a30 commit a69f3d1
Show file tree
Hide file tree
Showing 207 changed files with 208,801 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/cmd/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func GetCreateCmd() *cobra.Command {
createCmd.PersistentFlags().AddFlagSet(flagSet)

createCmd.AddCommand(getAWSProviderCmd())
createCmd.AddCommand(getGCPProviderCmd())

return createCmd
}
57 changes: 57 additions & 0 deletions cmd/cmd/create/gcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package create

import (
"fmt"
"os"

"github.com/crc/crc-cloud/cmd/cmd/constants"
"github.com/crc/crc-cloud/pkg/manager"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)

const (
gcpProviderName string = "gcp"
gcpProviderDescription string = "create crc cloud instance on GCP"
)

func getGCPProviderCmd() *cobra.Command {
gcpProviderCmd := &cobra.Command{
Use: gcpProviderName,
Short: gcpProviderDescription,
RunE: func(cmd *cobra.Command, args []string) error {
if err := viper.BindPFlags(cmd.Flags()); err != nil {
return err
}
// Provider dependent params
providerParams := make(map[string]string)
for name := range manager.CreateParams(manager.GCP) {
providerParams[name] = viper.GetString(name)
}
fmt.Printf("providerParams: %v", providerParams)
if err := manager.Create(
viper.GetString(constants.ProjectName),
viper.GetString(constants.BackedURL),
viper.GetString(constants.OutputFolder),
manager.GCP,
providerParams,
viper.GetString(constants.OcpPullSecretFilePath),
viper.GetString(constants.KeyFilePath),
viper.GetStringMapString(constants.Tags)); err != nil {
fmt.Printf("error creating the cluster with %s provider: %s\n", manager.GCP, err)
os.Exit(1)
}
return nil
},
}

flagSet := pflag.NewFlagSet(gcpProviderName, pflag.ExitOnError)
// Provider dependent params
for name, description := range manager.CreateParams(manager.GCP) {
flagSet.StringP(name, "", "", description)
}

gcpProviderCmd.Flags().AddFlagSet(flagSet)
return gcpProviderCmd
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/pulumi/pulumi-aws/sdk/v6 v6.0.4
github.com/pulumi/pulumi-azure-native-sdk/resources/v2 v2.6.0
github.com/pulumi/pulumi-azure-native-sdk/storage/v2 v2.6.0
github.com/pulumi/pulumi-gcp/sdk/v6 v6.65.0
github.com/pulumi/pulumi-tls/sdk/v4 v4.10.0
github.com/pulumi/pulumi/sdk/v3 v3.81.0
github.com/spf13/cobra v1.7.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,8 @@ github.com/pulumi/pulumi-azure-native-sdk/v2 v2.6.0 h1:owkaSHFQ+jdorX46+v8Mb//I1
github.com/pulumi/pulumi-azure-native-sdk/v2 v2.6.0/go.mod h1:0M4mUmmpe41qj02HAGJnLYLpf8TBkrtdqD6H8J9XPo4=
github.com/pulumi/pulumi-command/sdk v0.8.2 h1:ODz9nEjjX9/G0Xr+K99994xAs2ZBociLMssFKAWphBs=
github.com/pulumi/pulumi-command/sdk v0.8.2/go.mod h1:DAYVqHdbyWJopPk8/zJbB44XkwXj+kqUsPP4ZORiPWc=
github.com/pulumi/pulumi-gcp/sdk/v6 v6.65.0 h1:/pgEqIRV6C9O+AisKwNsTh5wxJ1iCwSSnB0VYAKjeps=
github.com/pulumi/pulumi-gcp/sdk/v6 v6.65.0/go.mod h1:XVpx0A3nUNUqnqqrD459QD6ExBRY4NyerNFuPAIPNmY=
github.com/pulumi/pulumi-random/sdk/v4 v4.13.2 h1:p4Cti4RIBKA0qi+JG/AofpcVsdyCaHd5gKMU5y/3I2Q=
github.com/pulumi/pulumi-random/sdk/v4 v4.13.2/go.mod h1:cFlJw0eQnqN+62QpITEF9M08gVyzNCeXrKRsuJptFak=
github.com/pulumi/pulumi-tls/sdk/v4 v4.10.0 h1:4MC0GyEomAjEZJPXEzBZpZ4+TOUg5WE77k38tMDIvS0=
Expand Down
3 changes: 3 additions & 0 deletions pkg/manager/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

providerAPI "github.com/crc/crc-cloud/pkg/manager/provider/api"
"github.com/crc/crc-cloud/pkg/provider/aws"
"github.com/crc/crc-cloud/pkg/provider/gcp"
)

type Provider string
Expand All @@ -19,6 +20,8 @@ func getProvider(provider Provider) (providerAPI.Provider, error) {
switch provider {
case AWS, AZ:
return aws.GetProvider(), nil
case GCP:
return gcp.GetProvider(), nil
}
return nil, fmt.Errorf("%s: provider not supported", provider)
}
16 changes: 16 additions & 0 deletions pkg/provider/gcp/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package gcp

const (

// Create params
imageID string = "gcp-image-id"
imageIDDesc string = "GCP image identifier"
instanceType string = "gcp-instance-type"
instanceTypeDesc string = "Instance type for the machine running the cluster. Default is n1-standard-8."
diskSize string = "gcp-disk-size"
diskSizeDesc string = "Disk size in GB for the machine running the cluster. Default is 100."

// default values
ocpInstanceType string = "n1-standard-8"
ocpDefaultRootBlockDeviceSize int = 100
)
170 changes: 170 additions & 0 deletions pkg/provider/gcp/create-instance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package gcp

import (
"fmt"
"github.com/crc/crc-cloud/pkg/bundle"
"github.com/crc/crc-cloud/pkg/bundle/setup"
providerAPI "github.com/crc/crc-cloud/pkg/manager/provider/api"
"github.com/crc/crc-cloud/pkg/util"
"github.com/pulumi/pulumi-gcp/sdk/v6/go/gcp/compute"
"github.com/pulumi/pulumi-tls/sdk/v4/go/tls"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
"strconv"
)

type createRequest struct {
projectName string
imageID string
instanceType string
diskSize int
bootingPrivateKeyFilePath string
ocpPullSecretFilePath string
}

func fillCreateRequest(projectName, bootingPrivateKeyFilePath, ocpPullSecretFilePath string,
args map[string]string) (*createRequest, error) {
imageIDValue, ok := args[imageID]
if !ok {
return nil, fmt.Errorf("imageID not found")
}
it := ocpInstanceType
if customInstanceType, ok := args[instanceType]; ok {
it = customInstanceType
}
ds := ocpDefaultRootBlockDeviceSize
if customDiskSizeAsString, ok := args[diskSize]; ok {
customDiskSize, err := strconv.Atoi(customDiskSizeAsString)
if err != nil {
return nil, fmt.Errorf("error creating request for cluster machine: %v", err)
}
ds = customDiskSize
}
return &createRequest{
projectName: projectName,
imageID: imageIDValue,
instanceType: it,
diskSize: ds,
bootingPrivateKeyFilePath: bootingPrivateKeyFilePath,
ocpPullSecretFilePath: ocpPullSecretFilePath}, nil
}

func (r createRequest) runFunc(ctx *pulumi.Context) error {
privateKey, err := createKey(ctx)
if err != nil {
return err
}
// Create a new network for the virtual machine.
network, err := compute.NewNetwork(ctx, r.projectName, &compute.NetworkArgs{
AutoCreateSubnetworks: pulumi.Bool(false),
})
if err != nil {
return err
}

// Create a subnet on the network.
subnet, err := compute.NewSubnetwork(ctx, r.projectName, &compute.SubnetworkArgs{
IpCidrRange: pulumi.String("10.0.1.0/24"),
Network: network.ID(),
})
if err != nil {
return err
}

// Create a firewall allowing inbound access over ports 80 (for HTTP) and 22 (for SSH).
firewall, err := compute.NewFirewall(ctx, r.projectName, &compute.FirewallArgs{
Network: network.SelfLink,
Allows: compute.FirewallAllowArray{
compute.FirewallAllowArgs{
Protocol: pulumi.String("tcp"),
Ports: pulumi.ToStringArray([]string{
"22", "443", "6443", "80",
}),
},
},
Direction: pulumi.String("INGRESS"),
SourceRanges: pulumi.ToStringArray([]string{
"0.0.0.0/0",
}),
TargetTags: pulumi.ToStringArray([]string{r.projectName}),
})
if err != nil {
return err
}

args := compute.InstanceArgs{
MachineType: pulumi.String(r.instanceType),
BootDisk: compute.InstanceBootDiskArgs{
InitializeParams: compute.InstanceBootDiskInitializeParamsArgs{
Image: pulumi.String(r.imageID),
},
},
NetworkInterfaces: compute.InstanceNetworkInterfaceArray{
compute.InstanceNetworkInterfaceArgs{
Network: network.ID(),
Subnetwork: subnet.ID(),
AccessConfigs: compute.InstanceNetworkInterfaceAccessConfigArray{
compute.InstanceNetworkInterfaceAccessConfigArgs{
// NatIp: nil,
// NetworkTier: nil,
},
},
},
},
ServiceAccount: compute.InstanceServiceAccountArgs{
Scopes: pulumi.ToStringArray([]string{
"https://www.googleapis.com/auth/cloud-platform",
}),
},
AllowStoppingForUpdate: pulumi.Bool(true),
Tags: pulumi.ToStringArray([]string{r.projectName}),
}

instance, err := compute.NewInstance(ctx, r.projectName, &args, pulumi.DependsOn([]pulumi.Resource{firewall}))
if err != nil {
return err
}

internalIP := instance.NetworkInterfaces.Index(pulumi.Int(0)).NetworkIp().Elem()
publicIP := instance.NetworkInterfaces.Index(pulumi.Int(0)).AccessConfigs().Index(pulumi.Int(0)).NatIp().Elem()

password, err := util.CreatePassword(ctx, "OpenshiftLocal-OCP")
if err != nil {
return err
}
_, err = setup.SwapKeys(ctx, &publicIP,
r.bootingPrivateKeyFilePath, &privateKey.PublicKeyOpenssh)
if err != nil {
return err
}
kubeconfig, _, err := setup.Setup(ctx,
&publicIP, &privateKey.PrivateKeyOpenssh,
setup.Data{
PrivateIP: &internalIP,
PublicIP: &publicIP,
Password: &password.Result,
OCPPullSecretFilePath: r.ocpPullSecretFilePath,
})
if err != nil {
return err
}
ctx.Export(providerAPI.Kubeconfig, kubeconfig)
ctx.Export(providerAPI.OutputKey, privateKey.PrivateKeyPem)
ctx.Export(providerAPI.OutputHost, publicIP)
ctx.Export(providerAPI.OutputUsername, pulumi.String(bundle.ImageUsername))
ctx.Export(providerAPI.OutputPassword, password.Result)
return nil
}

func createKey(ctx *pulumi.Context) (*tls.PrivateKey, error) {
pk, err := tls.NewPrivateKey(
ctx,
"OpenshiftLocal-OCP",
&tls.PrivateKeyArgs{
Algorithm: pulumi.String("RSA"),
RsaBits: pulumi.Int(4096),
})
if err != nil {
return nil, err
}
return pk, nil
}
43 changes: 43 additions & 0 deletions pkg/provider/gcp/gcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package gcp

import (
providerAPI "github.com/crc/crc-cloud/pkg/manager/provider/api"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

type Provider struct{}

func GetProvider() *Provider {
return &Provider{}
}

func (a *Provider) GetPlugin() *providerAPI.PluginInfo {
return &providerAPI.PluginInfo{
Name: "gcp",
Version: "v6.65.0"}
}

func (a *Provider) ImportImageRunFunc(projectName, bundleDownloadURL, shasumfileDownloadURL string) (pulumi.RunFunc, error) {
return nil, nil
}

func (a *Provider) CreateParams() map[string]string {
return map[string]string{
imageID: imageIDDesc,
instanceType: instanceTypeDesc,
diskSize: diskSizeDesc,
}
}

func (a *Provider) CreateParamsMandatory() []string {
return []string{imageID}
}

func (a *Provider) CreateRunFunc(projectName, bootingPrivateKeyFilePath, ocpPullSecretFilePath string,
args map[string]string) (pulumi.RunFunc, error) {
r, err := fillCreateRequest(projectName, bootingPrivateKeyFilePath, ocpPullSecretFilePath, args)
if err != nil {
return nil, err
}
return r.runFunc, nil
}
Loading

0 comments on commit a69f3d1

Please sign in to comment.