Skip to content
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
61 changes: 58 additions & 3 deletions pkg/asset/cluster/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,21 @@
package aws

import (
"context"
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/resourcegroupstaggingapi"
"github.com/sirupsen/logrus"

"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/types"
"github.com/openshift/installer/pkg/types/aws"
awstypes "github.com/openshift/installer/pkg/types/aws"
)

// Metadata converts an install configuration to AWS metadata.
func Metadata(clusterID, infraID string, config *types.InstallConfig) *aws.Metadata {
return &aws.Metadata{
func Metadata(clusterID, infraID string, config *types.InstallConfig) *awstypes.Metadata {
return &awstypes.Metadata{
Region: config.Platform.AWS.Region,
Identifier: []map[string]string{{
fmt.Sprintf("kubernetes.io/cluster/%s", infraID): "owned",
Expand All @@ -19,3 +25,52 @@ func Metadata(clusterID, infraID string, config *types.InstallConfig) *aws.Metad
}},
}
}

// PreTerraform performs any infrastructure initialization which must
// happen before Terraform creates the remaining infrastructure.
func PreTerraform(ctx context.Context, clusterID string, installConfig *installconfig.InstallConfig) error {
if len(installConfig.Config.Platform.AWS.Subnets) == 0 {
return nil
}

privateSubnets, err := installConfig.AWS.PrivateSubnets(ctx)
if err != nil {
return err
}

publicSubnets, err := installConfig.AWS.PublicSubnets(ctx)

arns := make([]string, 0, len(privateSubnets)+len(publicSubnets))
for _, subnet := range privateSubnets {
arns = append(arns, subnet.ARN)
}
for _, subnet := range publicSubnets {
arns = append(arns, subnet.ARN)
}

session, err := installConfig.AWS.Session(ctx)
if err != nil {
return err
}

request := &resourcegroupstaggingapi.TagResourcesInput{
Tags: map[string]*string{
fmt.Sprintf("kubernetes.io/cluster/%s", clusterID): aws.String("shared"),
},
}

tagClient := resourcegroupstaggingapi.New(session)
for i := 0; i < len(arns); i += 20 {
request.ResourceARNList = make([]*string, 0, 20)
for j := 0; i+j < len(arns) && j < 20; j++ {
logrus.Debugf("Tagging %s with kubernetes.io/cluster/%s: shared", arns[i+j], clusterID)
request.ResourceARNList = append(request.ResourceARNList, aws.String(arns[i+j]))
}
_, err = tagClient.TagResourcesWithContext(ctx, request)
if err != nil {
return err
}
}

return nil
}
8 changes: 8 additions & 0 deletions pkg/asset/cluster/cluster.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cluster

import (
"context"
"fmt"
"io/ioutil"
"os"
Expand All @@ -10,6 +11,7 @@ import (
"github.com/sirupsen/logrus"

"github.com/openshift/installer/pkg/asset"
"github.com/openshift/installer/pkg/asset/cluster/aws"
"github.com/openshift/installer/pkg/asset/installconfig"
"github.com/openshift/installer/pkg/asset/password"
"github.com/openshift/installer/pkg/terraform"
Expand Down Expand Up @@ -70,6 +72,12 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) {
}

logrus.Infof("Creating infrastructure resources...")
if installConfig.Config.Platform.AWS != nil {
if err := aws.PreTerraform(context.TODO(), clusterID.InfraID, installConfig); err != nil {
return err
}
}

stateFile, err := terraform.Apply(tmpDir, installConfig.Config.Platform.Name(), extraArgs...)
if err != nil {
err = errors.Wrap(err, "failed to create cluster")
Expand Down
36 changes: 33 additions & 3 deletions pkg/asset/cluster/tfvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func (t *TerraformVariables) Dependencies() []asset.Asset {

// Generate generates the terraform.tfvars file.
func (t *TerraformVariables) Generate(parents asset.Parents) error {
ctx := context.TODO()
clusterID := &installconfig.ClusterID{}
installConfig := &installconfig.InstallConfig{}
bootstrapIgnAsset := &bootstrap.Bootstrap{}
Expand Down Expand Up @@ -133,6 +134,35 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {

switch platform {
case aws.Name:
var vpc string
var privateSubnets []string
var publicSubnets []string

if len(installConfig.Config.Platform.AWS.Subnets) > 0 {
subnets, err := installConfig.AWS.PrivateSubnets(ctx)
if err != nil {
return err
}

for id := range subnets {
privateSubnets = append(privateSubnets, id)
}

subnets, err = installConfig.AWS.PublicSubnets(ctx)
if err != nil {
return err
}

for id := range subnets {
publicSubnets = append(publicSubnets, id)
}

vpc, err = installConfig.AWS.VPC(ctx)
if err != nil {
return err
}
}

masters, err := mastersAsset.Machines()
if err != nil {
return err
Expand All @@ -149,7 +179,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
for i, m := range workers {
workerConfigs[i] = m.Spec.Template.Spec.ProviderSpec.Value.Object.(*awsprovider.AWSMachineProviderConfig)
}
data, err := awstfvars.TFVars(masterConfigs, workerConfigs)
data, err := awstfvars.TFVars(vpc, privateSubnets, publicSubnets, masterConfigs, workerConfigs)
if err != nil {
return errors.Wrapf(err, "failed to get %s Terraform variables", platform)
}
Expand Down Expand Up @@ -203,7 +233,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
Data: data,
})
case gcp.Name:
sess, err := gcpconfig.GetSession(context.TODO())
sess, err := gcpconfig.GetSession(ctx)
if err != nil {
return err
}
Expand All @@ -225,7 +255,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
for i, w := range workers {
workerConfigs[i] = w.Spec.Template.Spec.ProviderSpec.Value.Object.(*gcpprovider.GCPMachineProviderSpec)
}
publicZone, err := gcpconfig.GetPublicZone(context.TODO(), installConfig.Config.GCP.ProjectID, installConfig.Config.BaseDomain)
publicZone, err := gcpconfig.GetPublicZone(ctx, installConfig.Config.GCP.ProjectID, installConfig.Config.BaseDomain)
if err != nil {
return errors.Wrapf(err, "failed to get GCP public zone")
}
Expand Down
75 changes: 73 additions & 2 deletions pkg/asset/installconfig/aws/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,17 @@ import (
type Metadata struct {
session *session.Session
availabilityZones []string
privateSubnets map[string]Subnet
publicSubnets map[string]Subnet
region string
subnets []string
vpc string
mutex sync.Mutex
}

// NewMetadata initializes a new Metadata object.
func NewMetadata(region string) *Metadata {
return &Metadata{region: region}
func NewMetadata(region string, subnets []string) *Metadata {
return &Metadata{region: region, subnets: subnets}
}

// Session holds an AWS session which can be used for AWS API calls
Expand Down Expand Up @@ -63,3 +67,70 @@ func (m *Metadata) AvailabilityZones(ctx context.Context) ([]string, error) {

return m.availabilityZones, nil
}

// PrivateSubnets retrieves subnet metadata indexed by subnet ID, for
// subnets that the cloud-provider logic considers to be private
// (i.e. not public).
func (m *Metadata) PrivateSubnets(ctx context.Context) (map[string]Subnet, error) {
m.mutex.Lock()
defer m.mutex.Unlock()

err := m.populateSubnets(ctx)
if err != nil {
return nil, err
}

return m.privateSubnets, nil
}

// PublicSubnets retrieves subnet metadata indexed by subnet ID, for
// subnets that the cloud-provider logic considers to be public
// (e.g. with suitable routing for hosting public load balancers).
func (m *Metadata) PublicSubnets(ctx context.Context) (map[string]Subnet, error) {
m.mutex.Lock()
defer m.mutex.Unlock()

err := m.populateSubnets(ctx)
if err != nil {
return nil, err
}

return m.publicSubnets, nil
}

func (m *Metadata) populateSubnets(ctx context.Context) error {
if len(m.publicSubnets) > 0 || len(m.privateSubnets) > 0 {
return nil
}

if len(m.subnets) == 0 {
return errors.New("no subnets configured")
}

session, err := m.unlockedSession(ctx)
if err != nil {
return err
}

m.vpc, m.privateSubnets, m.publicSubnets, err = subnets(ctx, session, m.subnets)
return err
}

// VPC retrieves the VPC ID containing PublicSubnets and PrivateSubnets.
func (m *Metadata) VPC(ctx context.Context) (string, error) {
m.mutex.Lock()
defer m.mutex.Unlock()

if m.vpc == "" {
if len(m.subnets) == 0 {
return "", errors.New("cannot calculate VPC without configured subnets")
}

err := m.populateSubnets(ctx)
if err != nil {
return "", err
}
}

return m.vpc, nil
}
Loading