Skip to content

Commit

Permalink
Merge pull request #971 from gcs278/release-4.12-shared-vpc
Browse files Browse the repository at this point in the history
[release-4.12] NE-1372: Add support for AWS shared VPC in another account #966
  • Loading branch information
openshift-merge-robot committed Sep 7, 2023
2 parents 3892bb3 + fb01b19 commit 0bb8ffc
Show file tree
Hide file tree
Showing 83 changed files with 12,671 additions and 18,768 deletions.
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -15,7 +15,7 @@ require (
github.com/go-logr/zapr v1.2.3
github.com/google/go-cmp v0.5.8
github.com/kevinburke/go-bindata v3.11.0+incompatible
github.com/openshift/api v0.0.0-20221010164355-920c3651ba3f
github.com/openshift/api v0.0.0-20230817133225-564be9ddb58e
github.com/openshift/client-go v0.0.0-20220831193253-4950ae70c8ea
github.com/openshift/library-go v0.0.0-20220920133651-093893cf326b
github.com/pkg/errors v0.9.1
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -541,8 +541,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48=
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
github.com/openshift/api v0.0.0-20221010164355-920c3651ba3f h1:jatN0nxy0dLfzevDe1NMO2mcb0/PeWKMrI2kXpHgGns=
github.com/openshift/api v0.0.0-20221010164355-920c3651ba3f/go.mod h1:JRz+ZvTqu9u7t6suhhPTacbFl5K65Y6rJbNM7HjWA3g=
github.com/openshift/api v0.0.0-20230817133225-564be9ddb58e h1:Hbw58VzpO9SktwYwXhiiubgvGmNTNeK6mxGtjPQ0uy4=
github.com/openshift/api v0.0.0-20230817133225-564be9ddb58e/go.mod h1:aQ6LDasvHMvHZXqLHnX2GRmnfTWCF/iIwz8EMTTIE9A=
github.com/openshift/client-go v0.0.0-20220831193253-4950ae70c8ea h1:7JbjIzWt3Q75ErY1PAZ+gCA+bErI6HSlpffHFmMMzqM=
github.com/openshift/client-go v0.0.0-20220831193253-4950ae70c8ea/go.mod h1:+J8DqZC60acCdpYkwVy/KH4cudgWiFZRNOBeghCzdGA=
github.com/openshift/library-go v0.0.0-20220920133651-093893cf326b h1:LWwB7uN91G/JsMnZFd0+q6ZzAXlB4/oUOfpZWA585gw=
Expand Down
2,695 changes: 894 additions & 1,801 deletions manifests/00-custom-resource-definition.yaml

Large diffs are not rendered by default.

15 changes: 14 additions & 1 deletion pkg/dns/aws/dns.go
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/endpoints"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
Expand Down Expand Up @@ -84,6 +85,10 @@ type Config struct {
// that is used by SDK to configure the credentials.
SharedCredentialFile string

// RoleARN is an optional ARN to use for the AWS client session that is
// intended to only provide access to another account's Route 53 service.
RoleARN string

// Region is the AWS region ELBs are created in.
Region string
// ServiceEndpoints is the list of AWS API endpoints to use for
Expand Down Expand Up @@ -137,6 +142,14 @@ func NewProvider(config Config, operatorReleaseVersion string) (*Provider, error
}
}

// When RoleARN is provided, make a copy of the Route 53 session and configure it to use RoleARN.
// RoleARN is intended to only provide access to another account's Route 53 service, not for ELBs.
sessRoute53 := sess
if config.RoleARN != "" {
sessRoute53 = sess.Copy()
sessRoute53.Config.WithCredentials(stscreds.NewCredentials(sessRoute53, config.RoleARN))
}

r53Config := aws.NewConfig()
// elb requires no special region treatment.
elbConfig := aws.NewConfig().WithRegion(region)
Expand Down Expand Up @@ -218,7 +231,7 @@ func NewProvider(config Config, operatorReleaseVersion string) (*Provider, error
// TODO: Add custom endpoint support for elbv2. See the following for details:
// https://docs.aws.amazon.com/general/latest/gr/elb.html
elbv2: elbv2.New(sess, aws.NewConfig().WithRegion(region)),
route53: route53.New(sess, r53Config),
route53: route53.New(sessRoute53, r53Config),
tags: tags,
config: config,
idsToTags: map[string]map[string]string{},
Expand Down
58 changes: 58 additions & 0 deletions pkg/dns/split/dns.go
@@ -0,0 +1,58 @@
package split

import (
"reflect"

iov1 "github.com/openshift/api/operatoringress/v1"
"github.com/openshift/cluster-ingress-operator/pkg/dns"
logf "github.com/openshift/cluster-ingress-operator/pkg/log"

configv1 "github.com/openshift/api/config/v1"
)

var (
_ dns.Provider = &Provider{}
log = logf.Logger.WithName("dns")
)

// Provider is a dns.Provider that wraps two other providers. The first
// provider is used for public hosted zones, and the second provider is used for
// private hosted zones.
type Provider struct {
private, public dns.Provider
privateZone *configv1.DNSZone
}

// NewProvider returns a new Provider that wraps the provided wrappers, using
// the first for the public zone and the second for the private zone.
func NewProvider(public, private dns.Provider, privateZone *configv1.DNSZone) *Provider {
return &Provider{
public: public,
private: private,
privateZone: privateZone,
}
}

// Ensure calls the Ensure method of one of the wrapped DNS providers.
func (p *Provider) Ensure(record *iov1.DNSRecord, zone configv1.DNSZone) error {
if reflect.DeepEqual(zone, *p.privateZone) {
return p.private.Ensure(record, zone)
}
return p.public.Ensure(record, zone)
}

// Delete calls the Delete method of one of the wrapped DNS providers.
func (p *Provider) Delete(record *iov1.DNSRecord, zone configv1.DNSZone) error {
if reflect.DeepEqual(zone, *p.privateZone) {
return p.private.Delete(record, zone)
}
return p.public.Delete(record, zone)
}

// Replace calls the Replace method of one of the wrapped DNS providers.
func (p *Provider) Replace(record *iov1.DNSRecord, zone configv1.DNSZone) error {
if reflect.DeepEqual(zone, *p.privateZone) {
return p.private.Replace(record, zone)
}
return p.public.Replace(record, zone)
}
126 changes: 126 additions & 0 deletions pkg/dns/split/dns_test.go
@@ -0,0 +1,126 @@
package split_test

import (
"testing"

"github.com/stretchr/testify/assert"

configv1 "github.com/openshift/api/config/v1"
iov1 "github.com/openshift/api/operatoringress/v1"

"github.com/openshift/cluster-ingress-operator/pkg/dns"
splitdns "github.com/openshift/cluster-ingress-operator/pkg/dns/split"
)

// TestSplitDNSProvider verifies that the split DNS provider dispatches to the
// public or private provider as appropriate for the DNS zone.
func TestSplitDNSProvider(t *testing.T) {
var (
// ch is a channel that is used in the fake public and private
// providers to record which one is called.
ch = make(chan string, 6)
// getResult reads and returns one item from ch, or returns the
// empty string if ch is empty.
getResult = func() string {
var result string
select {
case result = <-ch:
default:
}
return result
}
// publicProvider is a fake dns.Provider for the public zone.
publicProvider = newFakeProvider("public", ch)
// privateProvider is a fake dns.Provider for the private zone.
privateProvider = newFakeProvider("private", ch)
// publicZoneWithID is a public zone that is defined by ID.
publicZoneWithID = configv1.DNSZone{ID: "public_zone"}
// privateZoneWithID is a private zone that is defined by ID.
privateZoneWithID = configv1.DNSZone{ID: "private_zone"}
// publicZoneWithTags is a public zone that is defined by tags.
publicZoneWithTags = configv1.DNSZone{Tags: map[string]string{"zone": "public"}}
// privateZoneWithID is a private zone that is defined by tags.
privateZoneWithTags = configv1.DNSZone{Tags: map[string]string{"zone": "private"}}
)
testCases := []struct {
name string
publicZone configv1.DNSZone
privateZone configv1.DNSZone
publishToZone configv1.DNSZone
expect string
}{
{
name: "publish to public zone specified by id",
publicZone: publicZoneWithID,
privateZone: privateZoneWithID,
publishToZone: publicZoneWithID,
expect: "public",
},
{
name: "publish to private zone specified by id",
publicZone: publicZoneWithID,
privateZone: privateZoneWithID,
publishToZone: privateZoneWithID,
expect: "private",
},
{
name: "publish to public zone specified by tags",
publicZone: publicZoneWithTags,
privateZone: privateZoneWithID,
publishToZone: publicZoneWithTags,
expect: "public",
},
{
name: "publish to private zone specified by tags",
publicZone: publicZoneWithTags,
privateZone: privateZoneWithTags,
publishToZone: privateZoneWithTags,
expect: "private",
},
{
name: "publish to other zone should fall back to the public zone",
publicZone: publicZoneWithID,
privateZone: privateZoneWithID,
publishToZone: configv1.DNSZone{ID: "other_zone"},
expect: "public",
},
}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
provider := splitdns.NewProvider(publicProvider, privateProvider, &tc.privateZone)
assert.NoError(t, provider.Ensure(&iov1.DNSRecord{}, tc.publishToZone))
assert.Equal(t, tc.expect, getResult())
assert.NoError(t, provider.Replace(&iov1.DNSRecord{}, tc.publishToZone))
assert.Equal(t, tc.expect, getResult())
assert.NoError(t, provider.Delete(&iov1.DNSRecord{}, tc.publishToZone))
assert.Equal(t, tc.expect, getResult())
assert.Empty(t, ch)
})
}

}

var _ dns.Provider = &fakeProvider{}

type fakeProvider struct {
name string
recorder chan string
}

func (p *fakeProvider) Ensure(record *iov1.DNSRecord, zone configv1.DNSZone) error {
p.recorder <- p.name
return nil
}
func (p *fakeProvider) Delete(record *iov1.DNSRecord, zone configv1.DNSZone) error {
p.recorder <- p.name
return nil
}
func (p *fakeProvider) Replace(record *iov1.DNSRecord, zone configv1.DNSZone) error {
p.recorder <- p.name
return nil
}

// newFakeProvider returns a new dns.Provider that records invocations.
func newFakeProvider(name string, ch chan string) dns.Provider {
return &fakeProvider{name, ch}
}
8 changes: 4 additions & 4 deletions pkg/manifests/bindata.go

Large diffs are not rendered by default.

17 changes: 16 additions & 1 deletion pkg/operator/controller/dns/controller.go
Expand Up @@ -22,6 +22,7 @@ import (
ibm "github.com/openshift/cluster-ingress-operator/pkg/dns/ibm"
ibmprivatedns "github.com/openshift/cluster-ingress-operator/pkg/dns/ibm/private"
ibmpublicdns "github.com/openshift/cluster-ingress-operator/pkg/dns/ibm/public"
splitdns "github.com/openshift/cluster-ingress-operator/pkg/dns/split"
logf "github.com/openshift/cluster-ingress-operator/pkg/log"
"github.com/openshift/cluster-ingress-operator/pkg/manifests"
"github.com/openshift/cluster-ingress-operator/pkg/operator/controller"
Expand Down Expand Up @@ -670,7 +671,21 @@ func (r *reconciler) createDNSProvider(dnsConfig *configv1.DNS, platformStatus *
if err != nil {
return nil, fmt.Errorf("failed to create AWS DNS manager: %v", err)
}
dnsProvider = provider
var roleARN string
if dnsConfig.Spec.Platform.AWS != nil {
roleARN = dnsConfig.Spec.Platform.AWS.PrivateZoneIAMRole
}
if roleARN != "" {
cfg := cfg
cfg.RoleARN = roleARN
privateProvider, err := awsdns.NewProvider(cfg, r.config.OperatorReleaseVersion)
if err != nil {
return nil, fmt.Errorf("failed to create AWS DNS manager for shared VPC: %v", err)
}
dnsProvider = splitdns.NewProvider(provider, privateProvider, dnsConfig.Spec.PrivateZone)
} else {
dnsProvider = provider
}
case configv1.AzurePlatformType:
environment := platformStatus.Azure.CloudName
if environment == "" {
Expand Down

0 comments on commit 0bb8ffc

Please sign in to comment.