constellation/cli/internal/cloudcmd/create.go

179 lines
5.6 KiB
Go
Raw Normal View History

2022-04-13 07:01:38 -04:00
package cloudcmd
import (
"context"
"fmt"
"io"
2022-06-07 10:30:41 -04:00
azurecl "github.com/edgelesssys/constellation/cli/internal/azure/client"
2022-06-07 08:52:47 -04:00
"github.com/edgelesssys/constellation/cli/internal/gcp"
gcpcl "github.com/edgelesssys/constellation/cli/internal/gcp/client"
"github.com/edgelesssys/constellation/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/internal/cloud/cloudtypes"
2022-04-13 07:01:38 -04:00
"github.com/edgelesssys/constellation/internal/config"
"github.com/edgelesssys/constellation/internal/state"
)
// Creator creates cloud resources.
type Creator struct {
out io.Writer
newGCPClient func(ctx context.Context, project, zone, region, name string) (gcpclient, error)
newAzureClient func(subscriptionID, tenantID, name, location string) (azureclient, error)
}
// NewCreator creates a new creator.
func NewCreator(out io.Writer) *Creator {
return &Creator{
out: out,
newGCPClient: func(ctx context.Context, project, zone, region, name string) (gcpclient, error) {
return gcpcl.NewInitialized(ctx, project, zone, region, name)
},
newAzureClient: func(subscriptionID, tenantID, name, location string) (azureclient, error) {
return azurecl.NewInitialized(subscriptionID, tenantID, name, location)
},
}
}
// Create creates the handed amount of instances and all the needed resources.
func (c *Creator) Create(ctx context.Context, provider cloudprovider.Provider, config *config.Config, name, insType string, controlPlaneCount, workerCount int,
2022-04-13 07:01:38 -04:00
) (state.ConstellationState, error) {
switch provider {
case cloudprovider.GCP:
cl, err := c.newGCPClient(
ctx,
config.Provider.GCP.Project,
config.Provider.GCP.Zone,
config.Provider.GCP.Region,
2022-04-13 07:01:38 -04:00
name,
)
if err != nil {
return state.ConstellationState{}, err
}
defer cl.Close()
return c.createGCP(ctx, cl, config, insType, controlPlaneCount, workerCount)
2022-04-13 07:01:38 -04:00
case cloudprovider.Azure:
cl, err := c.newAzureClient(
config.Provider.Azure.SubscriptionID,
config.Provider.Azure.TenantID,
2022-04-13 07:01:38 -04:00
name,
config.Provider.Azure.Location,
2022-04-13 07:01:38 -04:00
)
if err != nil {
return state.ConstellationState{}, err
}
return c.createAzure(ctx, cl, config, insType, controlPlaneCount, workerCount)
2022-04-13 07:01:38 -04:00
default:
return state.ConstellationState{}, fmt.Errorf("unsupported cloud provider: %s", provider)
}
}
func (c *Creator) createGCP(ctx context.Context, cl gcpclient, config *config.Config, insType string, controlPlaneCount, workerCount int,
2022-04-13 07:01:38 -04:00
) (stat state.ConstellationState, retErr error) {
defer rollbackOnError(context.Background(), c.out, &retErr, &rollbackerGCP{client: cl})
if err := cl.CreateVPCs(ctx); err != nil {
2022-04-13 07:01:38 -04:00
return state.ConstellationState{}, err
}
if err := cl.CreateFirewall(ctx, gcpcl.FirewallInput{
Ingress: cloudtypes.Firewall(config.IngressFirewall),
Egress: cloudtypes.Firewall(config.EgressFirewall),
}); err != nil {
2022-04-13 07:01:38 -04:00
return state.ConstellationState{}, err
}
2022-05-24 04:04:42 -04:00
// additionally create allow-internal rules
internalFirewallInput := gcpcl.FirewallInput{
Ingress: cloudtypes.Firewall{
{
Name: "allow-cluster-internal-tcp",
Protocol: "tcp",
IPRange: gcpcl.SubnetExtCIDR,
},
{
Name: "allow-cluster-internal-udp",
Protocol: "udp",
IPRange: gcpcl.SubnetExtCIDR,
},
{
Name: "allow-cluster-internal-icmp",
Protocol: "icmp",
IPRange: gcpcl.SubnetExtCIDR,
},
{
Name: "allow-node-internal-tcp",
Protocol: "tcp",
IPRange: gcpcl.SubnetCIDR,
},
{
Name: "allow-node-internal-udp",
Protocol: "udp",
IPRange: gcpcl.SubnetCIDR,
},
{
Name: "allow-node-internal-icmp",
Protocol: "icmp",
IPRange: gcpcl.SubnetCIDR,
},
},
}
if err := cl.CreateFirewall(ctx, internalFirewallInput); err != nil {
return state.ConstellationState{}, err
}
2022-06-07 08:52:47 -04:00
createInput := gcpcl.CreateInstancesInput{
CountControlPlanes: controlPlaneCount,
CountWorkers: workerCount,
ImageID: config.Provider.GCP.Image,
InstanceType: insType,
StateDiskSizeGB: config.StateDiskSizeGB,
KubeEnv: gcp.KubeEnv,
2022-04-13 07:01:38 -04:00
}
if err := cl.CreateInstances(ctx, createInput); err != nil {
return state.ConstellationState{}, err
}
2022-06-09 16:26:36 -04:00
if err := cl.CreateLoadBalancer(ctx); err != nil {
return state.ConstellationState{}, err
}
2022-04-13 07:01:38 -04:00
return cl.GetState()
}
func (c *Creator) createAzure(ctx context.Context, cl azureclient, config *config.Config, insType string, controlPlaneCount, workerCount int,
2022-04-13 07:01:38 -04:00
) (stat state.ConstellationState, retErr error) {
defer rollbackOnError(context.Background(), c.out, &retErr, &rollbackerAzure{client: cl})
if err := cl.CreateResourceGroup(ctx); err != nil {
return state.ConstellationState{}, err
}
if err := cl.CreateApplicationInsight(ctx); err != nil {
return state.ConstellationState{}, err
}
2022-05-24 04:04:42 -04:00
if err := cl.CreateExternalLoadBalancer(ctx); err != nil {
return state.ConstellationState{}, err
}
2022-04-13 07:01:38 -04:00
if err := cl.CreateVirtualNetwork(ctx); err != nil {
return state.ConstellationState{}, err
}
if err := cl.CreateSecurityGroup(ctx, azurecl.NetworkSecurityGroupInput{
Ingress: cloudtypes.Firewall(config.IngressFirewall),
Egress: cloudtypes.Firewall(config.EgressFirewall),
}); err != nil {
2022-04-13 07:01:38 -04:00
return state.ConstellationState{}, err
}
createInput := azurecl.CreateInstancesInput{
CountControlPlanes: controlPlaneCount,
CountWorkers: workerCount,
2022-04-13 07:01:38 -04:00
InstanceType: insType,
StateDiskSizeGB: config.StateDiskSizeGB,
Image: config.Provider.Azure.Image,
UserAssingedIdentity: config.Provider.Azure.UserAssignedIdentity,
2022-04-13 07:01:38 -04:00
}
if err := cl.CreateInstances(ctx, createInput); err != nil {
return state.ConstellationState{}, err
}
return cl.GetState()
}