Skip to content

Commit bf24c3e

Browse files
Merge pull request openshift#8532 from mjturek/permitted-network
OCPBUGS-34978: Power VS: Ensure that VPC has prerequesite resources for private
2 parents 5dc4c97 + bad2886 commit bf24c3e

File tree

4 files changed

+171
-1
lines changed

4 files changed

+171
-1
lines changed

pkg/asset/installconfig/powervs/client.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ type API interface {
4141
GetDNSZones(ctx context.Context, publish types.PublishingStrategy) ([]DNSZoneResponse, error)
4242
GetDNSInstancePermittedNetworks(ctx context.Context, dnsID string, dnsZone string) ([]string, error)
4343
GetDNSCustomResolverIP(ctx context.Context, dnsID string, vpcID string) (string, error)
44+
CreateDNSCustomResolver(ctx context.Context, name string, dnsID string, vpcID string) (*dnssvcsv1.CustomResolver, error)
45+
EnableDNSCustomResolver(ctx context.Context, dnsID string, resolverID string) (*dnssvcsv1.CustomResolver, error)
4446
CreateDNSRecord(ctx context.Context, publish types.PublishingStrategy, crnstr string, baseDomain string, hostname string, cname string) error
47+
AddVPCToPermittedNetworks(ctx context.Context, vpcCRN string, dnsID string, dnsZone string) error
4548

4649
// VPC
4750
GetVPCByName(ctx context.Context, vpcName string) (*vpcv1.VPC, error)
@@ -295,6 +298,46 @@ func (c *Client) GetDNSCustomResolverIP(ctx context.Context, dnsID string, vpcID
295298
return "", fmt.Errorf("DNS server IP of custom resolver for %q not found", dnsID)
296299
}
297300

301+
// CreateDNSCustomResolver creates a custom resolver associated with the specified VPC in the specified DNS zone.
302+
func (c *Client) CreateDNSCustomResolver(ctx context.Context, name string, dnsID string, vpcID string) (*dnssvcsv1.CustomResolver, error) {
303+
createCustomResolverOptions := c.dnsServicesAPI.NewCreateCustomResolverOptions(dnsID)
304+
createCustomResolverOptions.SetName(name)
305+
306+
subnets, err := c.GetVPCSubnets(ctx, vpcID)
307+
if err != nil {
308+
return nil, err
309+
}
310+
311+
locations := []dnssvcsv1.LocationInput{}
312+
for _, subnet := range subnets {
313+
location, err := c.dnsServicesAPI.NewLocationInput(*subnet.CRN)
314+
if err != nil {
315+
return nil, err
316+
}
317+
location.Enabled = core.BoolPtr(true)
318+
locations = append(locations, *location)
319+
}
320+
createCustomResolverOptions.SetLocations(locations)
321+
322+
customResolver, _, err := c.dnsServicesAPI.CreateCustomResolverWithContext(ctx, createCustomResolverOptions)
323+
if err != nil {
324+
return nil, err
325+
}
326+
return customResolver, nil
327+
}
328+
329+
// EnableDNSCustomResolver enables a specified custom resolver.
330+
func (c *Client) EnableDNSCustomResolver(ctx context.Context, dnsID string, resolverID string) (*dnssvcsv1.CustomResolver, error) {
331+
updateCustomResolverOptions := c.dnsServicesAPI.NewUpdateCustomResolverOptions(dnsID, resolverID)
332+
updateCustomResolverOptions.SetEnabled(true)
333+
334+
customResolver, _, err := c.dnsServicesAPI.UpdateCustomResolverWithContext(ctx, updateCustomResolverOptions)
335+
if err != nil {
336+
return nil, err
337+
}
338+
return customResolver, nil
339+
}
340+
298341
// GetDNSZoneIDByName gets the CIS zone ID from its domain name.
299342
func (c *Client) GetDNSZoneIDByName(ctx context.Context, name string, publish types.PublishingStrategy) (string, error) {
300343
zones, err := c.GetDNSZones(ctx, publish)
@@ -416,6 +459,24 @@ func (c *Client) GetDNSInstancePermittedNetworks(ctx context.Context, dnsID stri
416459
return networks, nil
417460
}
418461

462+
// AddVPCToPermittedNetworks adds the specified VPC to the specified DNS zone.
463+
func (c *Client) AddVPCToPermittedNetworks(ctx context.Context, vpcCRN string, dnsID string, dnsZone string) error {
464+
createPermittedNetworkOptions := c.dnsServicesAPI.NewCreatePermittedNetworkOptions(dnsID, dnsZone)
465+
permittedNetwork, err := c.dnsServicesAPI.NewPermittedNetworkVpc(vpcCRN)
466+
if err != nil {
467+
return err
468+
}
469+
470+
createPermittedNetworkOptions.SetPermittedNetwork(permittedNetwork)
471+
createPermittedNetworkOptions.SetType("vpc")
472+
473+
_, _, err = c.dnsServicesAPI.CreatePermittedNetworkWithContext(ctx, createPermittedNetworkOptions)
474+
if err != nil {
475+
return err
476+
}
477+
return nil
478+
}
479+
419480
// CreateDNSRecord Creates a DNS CNAME record in the given base domain and CRN.
420481
func (c *Client) CreateDNSRecord(ctx context.Context, publish types.PublishingStrategy, crnstr string, baseDomain string, hostname string, cname string) error {
421482
switch publish {

pkg/asset/installconfig/powervs/metadata.go

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,36 @@ func (m *Metadata) IsVPCPermittedNetwork(ctx context.Context, vpcName string, ba
246246
return false, nil
247247
}
248248

249+
// EnsureVPCIsPermittedNetwork checks if a VPC is permitted to the DNS zone and adds it if it is not.
250+
func (m *Metadata) EnsureVPCIsPermittedNetwork(ctx context.Context, vpcName string) error {
251+
dnsCRN, err := crn.Parse(m.dnsInstanceCRN)
252+
if err != nil {
253+
return fmt.Errorf("failed to parse DNSInstanceCRN: %w", err)
254+
}
255+
256+
isVPCPermittedNetwork, err := m.IsVPCPermittedNetwork(ctx, vpcName, m.BaseDomain)
257+
if err != nil {
258+
return fmt.Errorf("failed to determine if VPC is permitted network: %w", err)
259+
}
260+
261+
if !isVPCPermittedNetwork {
262+
vpc, err := m.client.GetVPCByName(ctx, vpcName)
263+
if err != nil {
264+
return fmt.Errorf("failed to find VPC by name: %w", err)
265+
}
266+
267+
zoneID, err := m.client.GetDNSZoneIDByName(ctx, m.BaseDomain, types.InternalPublishingStrategy)
268+
if err != nil {
269+
return fmt.Errorf("failed to get DNS zone ID: %w", err)
270+
}
271+
err = m.client.AddVPCToPermittedNetworks(ctx, *vpc.CRN, dnsCRN.ServiceInstance, zoneID)
272+
if err != nil {
273+
return fmt.Errorf("failed to add permitted network: %w", err)
274+
}
275+
}
276+
return nil
277+
}
278+
249279
// GetSubnetID gets the ID of a VPC subnet by name and region.
250280
func (m *Metadata) GetSubnetID(ctx context.Context, subnetName string, vpcRegion string) (string, error) {
251281
subnet, err := m.client.GetSubnetByName(ctx, subnetName, vpcRegion)
@@ -281,7 +311,35 @@ func (m *Metadata) GetDNSServerIP(ctx context.Context, vpcName string) (string,
281311
}
282312
dnsServerIP, err := m.client.GetDNSCustomResolverIP(ctx, dnsCRN.ServiceInstance, *vpc.ID)
283313
if err != nil {
284-
return "", err
314+
// There is no custom resolver, try to create one.
315+
customResolverName := fmt.Sprintf("%s-custom-resolver", vpcName)
316+
customResolver, err := m.client.CreateDNSCustomResolver(ctx, customResolverName, dnsCRN.ServiceInstance, *vpc.ID)
317+
if err != nil {
318+
return "", err
319+
}
320+
// Wait for the custom resolver to be enabled.
321+
backoff := wait.Backoff{
322+
Duration: 15 * time.Second,
323+
Factor: 1.1,
324+
Cap: leftInContext(ctx),
325+
Steps: math.MaxInt32}
326+
327+
customResolverID := *customResolver.ID
328+
var lastErr error
329+
err = wait.ExponentialBackoffWithContext(ctx, backoff, func(context.Context) (bool, error) {
330+
customResolver, lastErr = m.client.EnableDNSCustomResolver(ctx, dnsCRN.ServiceInstance, customResolverID)
331+
if lastErr == nil {
332+
return true, nil
333+
}
334+
return false, nil
335+
})
336+
if err != nil {
337+
if lastErr != nil {
338+
err = lastErr
339+
}
340+
return "", fmt.Errorf("failed to enable custom resolver %s: %w", *customResolver.ID, err)
341+
}
342+
dnsServerIP = *customResolver.Locations[0].DnsServerIp
285343
}
286344
return dnsServerIP, nil
287345
}

pkg/asset/installconfig/powervs/mock/powervsclient_generated.go

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/asset/manifests/powervs/cluster.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,12 @@ func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID
181181
// If a VPC was specified, pass all subnets in it to cluster API
182182
if installConfig.Config.Platform.PowerVS.VPCName != "" {
183183
logrus.Debugf("GenerateClusterAssets: VPCName = %s", installConfig.Config.Platform.PowerVS.VPCName)
184+
if installConfig.Config.Publish == types.InternalPublishingStrategy {
185+
err = installConfig.PowerVS.EnsureVPCIsPermittedNetwork(context.TODO(), installConfig.Config.PowerVS.VPCName)
186+
}
187+
if err != nil {
188+
return nil, fmt.Errorf("error ensuring VPC is permitted: %s %w", installConfig.Config.PowerVS.VPCName, err)
189+
}
184190
subnets, err := installConfig.PowerVS.GetVPCSubnets(context.TODO(), vpcName)
185191
if err != nil {
186192
return nil, fmt.Errorf("error getting subnets in specified VPC: %s %w", installConfig.Config.PowerVS.VPCName, err)

0 commit comments

Comments
 (0)