Skip to content

Commit bad2886

Browse files
committed
Power VS: Ensure that VPC has prerequesite resources for private.
Currently the installer will not add your VPC as a permitted network for private DNS. It will also expect that a custom resolver is created and enabled. Adding this ability to the installer will make using private DNS easier.
1 parent d0d6bad commit bad2886

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
@@ -40,7 +40,10 @@ type API interface {
4040
GetDNSZones(ctx context.Context, publish types.PublishingStrategy) ([]DNSZoneResponse, error)
4141
GetDNSInstancePermittedNetworks(ctx context.Context, dnsID string, dnsZone string) ([]string, error)
4242
GetDNSCustomResolverIP(ctx context.Context, dnsID string, vpcID string) (string, error)
43+
CreateDNSCustomResolver(ctx context.Context, name string, dnsID string, vpcID string) (*dnssvcsv1.CustomResolver, error)
44+
EnableDNSCustomResolver(ctx context.Context, dnsID string, resolverID string) (*dnssvcsv1.CustomResolver, error)
4345
CreateDNSRecord(ctx context.Context, publish types.PublishingStrategy, crnstr string, baseDomain string, hostname string, cname string) error
46+
AddVPCToPermittedNetworks(ctx context.Context, vpcCRN string, dnsID string, dnsZone string) error
4447

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

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

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