github.com/openshift/installer@v1.4.17/pkg/asset/cluster/azure/azure.go (about) 1 // Package azure extracts AZURE metadata from install configurations. 2 package azure 3 4 import ( 5 "context" 6 "fmt" 7 "time" 8 9 "github.com/Azure/azure-sdk-for-go/profiles/2018-03-01/resources/mgmt/resources" 10 "github.com/Azure/azure-sdk-for-go/sdk/azcore" 11 "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm" 12 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork" 13 "github.com/Azure/go-autorest/autorest/to" 14 "github.com/sirupsen/logrus" 15 16 "github.com/openshift/installer/pkg/asset/installconfig" 17 icazure "github.com/openshift/installer/pkg/asset/installconfig/azure" 18 "github.com/openshift/installer/pkg/types" 19 "github.com/openshift/installer/pkg/types/azure" 20 ) 21 22 // Metadata converts an install configuration to Azure metadata. 23 func Metadata(config *types.InstallConfig) *azure.Metadata { 24 return &azure.Metadata{ 25 ARMEndpoint: config.Platform.Azure.ARMEndpoint, 26 CloudName: config.Platform.Azure.CloudName, 27 Region: config.Platform.Azure.Region, 28 ResourceGroupName: config.Azure.ResourceGroupName, 29 BaseDomainResourceGroupName: config.Azure.BaseDomainResourceGroupName, 30 } 31 } 32 33 // PreTerraform performs any infrastructure initialization which must 34 // happen before Terraform creates the remaining infrastructure. 35 func PreTerraform(ctx context.Context, clusterID string, installConfig *installconfig.InstallConfig) error { 36 session, err := installConfig.Azure.Session() 37 if err != nil { 38 return fmt.Errorf("failed to get session: %w", err) 39 } 40 41 if err := tagResourceGroup(ctx, clusterID, installConfig, session); err != nil { 42 return err 43 } 44 45 // removing shared tags relies on an api that isn't available 46 // on azure stack hub, so we do not tag them as to not leak 47 // the tags. see pkg/destroy/azure/azure.go for more. 48 if installConfig.Azure.CloudName != azure.StackCloud { 49 err = tagVNet(ctx, clusterID, installConfig, session) 50 } 51 return err 52 } 53 54 func tagVNet(ctx context.Context, clusterID string, installConfig *installconfig.InstallConfig, session *icazure.Session) error { 55 if len(installConfig.Config.Azure.VirtualNetwork) == 0 { 56 return nil 57 } 58 59 resourceGroupName := installConfig.Config.Azure.NetworkResourceGroupName 60 clientOpts := &arm.ClientOptions{ 61 ClientOptions: azcore.ClientOptions{ 62 Cloud: session.CloudConfig, 63 }, 64 } 65 66 vnetClient, err := armnetwork.NewVirtualNetworksClient(session.Credentials.SubscriptionID, session.TokenCreds, clientOpts) 67 if err != nil { 68 return fmt.Errorf("failed to get the virtual network client: %w", err) 69 } 70 71 vnetResp, err := vnetClient.Get(ctx, resourceGroupName, installConfig.Config.Azure.VirtualNetwork, nil) 72 if err != nil { 73 return fmt.Errorf("failed to get the virtual network %q: %w", installConfig.Config.Azure.VirtualNetwork, err) 74 } 75 vnet := vnetResp.VirtualNetwork 76 if vnet.Tags == nil { 77 vnet.Tags = map[string]*string{} 78 } 79 tagKey, tagValue := sharedTag(clusterID) 80 vnet.Tags[tagKey] = tagValue 81 82 tags := armnetwork.TagsObject{ 83 Tags: vnet.Tags, 84 } 85 86 logrus.Debugf("Tagging vnet %s with %s: %s", installConfig.Config.Azure.VirtualNetwork, tagKey, *tagValue) 87 88 if _, err := vnetClient.UpdateTags( 89 ctx, resourceGroupName, installConfig.Config.Azure.VirtualNetwork, tags, nil, 90 ); err != nil { 91 return fmt.Errorf("failed to update virtual network tags: %w", err) 92 } 93 94 return nil 95 } 96 97 func tagResourceGroup(ctx context.Context, clusterID string, installConfig *installconfig.InstallConfig, session *icazure.Session) error { 98 if len(installConfig.Config.Azure.ResourceGroupName) == 0 { 99 return nil 100 } 101 102 client := resources.NewGroupsClientWithBaseURI(session.Environment.ResourceManagerEndpoint, session.Credentials.SubscriptionID) 103 client.Authorizer = session.Authorizer 104 ctx, cancel := context.WithTimeout(ctx, 30*time.Second) 105 defer cancel() 106 107 group, err := client.Get(ctx, installConfig.Config.Azure.ResourceGroupName) 108 if err != nil { 109 return fmt.Errorf("failed to get the resource group: %w", err) 110 } 111 112 if group.Tags == nil { 113 group.Tags = map[string]*string{} 114 } 115 116 // The cluster resource group when created by the installer is tagged with `kubernetes.io_cluster_<infraID>=owned` tag. 117 // This tag is used to clean up the service principles generated by cred-minter and also to mark that the resource group is owned by 118 // this specific cluster. 119 // 120 // Since user provided resource group still is owned by the cluster, we must tag this resource group similarly. Since terraform cannot 121 // update the tags for an existing resource group, we have to fall back the pattern of `PreTerraform` previously used by AWS for pre-existing subnets. 122 // 123 // We read existing tags from the resource group and add `kubernetes.io_cluster_<infraID>=owned` to it when sending an update for the resource group. 124 tagKey, tagValue := ownedTag(clusterID) 125 group.Tags[tagKey] = tagValue 126 logrus.Debugf("Tagging resource group %s with %s: %s", installConfig.Config.Azure.ResourceGroupName, tagKey, *tagValue) 127 128 // Save metadata needed to destroy cluster into tags 129 config := installConfig.Config.Azure 130 group.Tags[azure.TagMetadataRegion] = to.StringPtr(config.Region) 131 if len(config.BaseDomainResourceGroupName) > 0 { 132 group.Tags[azure.TagMetadataBaseDomainRG] = to.StringPtr(config.BaseDomainResourceGroupName) 133 } 134 if len(config.NetworkResourceGroupName) > 0 { 135 group.Tags[azure.TagMetadataNetworkRG] = to.StringPtr(config.NetworkResourceGroupName) 136 } 137 138 _, err = client.Update(ctx, installConfig.Config.Azure.ResourceGroupName, resources.GroupPatchable{ 139 Tags: group.Tags, 140 }) 141 if err != nil { 142 return fmt.Errorf("failed to tag the resource group %q: %w", installConfig.Config.Azure.ResourceGroupName, err) 143 } 144 return nil 145 } 146 147 func sharedTag(clusterID string) (string, *string) { 148 return fmt.Sprintf("kubernetes.io_cluster.%s", clusterID), to.StringPtr("shared") 149 } 150 151 func ownedTag(clusterID string) (string, *string) { 152 return fmt.Sprintf("kubernetes.io_cluster.%s", clusterID), to.StringPtr("owned") 153 }