github.com/kubernetes-sigs/azuredisk-csi-driver@v0.7.0/test/utils/azure/azure_helpers.go (about) 1 /* 2 Copyright 2020 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package azure 18 19 import ( 20 "context" 21 "fmt" 22 "log" 23 "os" 24 "time" 25 26 "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-03-01/compute" 27 "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2018-08-01/network" 28 "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/resources" 29 "github.com/Azure/go-autorest/autorest" 30 "github.com/Azure/go-autorest/autorest/adal" 31 "github.com/Azure/go-autorest/autorest/azure" 32 "github.com/Azure/go-autorest/autorest/to" 33 ) 34 35 type AzureClient struct { 36 environment azure.Environment 37 subscriptionID string 38 groupsClient resources.GroupsClient 39 vmClient compute.VirtualMachinesClient 40 nicClient network.InterfacesClient 41 subnetsClient network.SubnetsClient 42 vnetClient network.VirtualNetworksClient 43 } 44 45 func GetAzureClient(cloud, subscriptionID, clientID, tenantID, clientSecret string) (*AzureClient, error) { 46 env, err := azure.EnvironmentFromName(cloud) 47 if err != nil { 48 return nil, err 49 } 50 51 oauthConfig, err := getOAuthConfig(env, subscriptionID, tenantID) 52 if err != nil { 53 return nil, err 54 } 55 56 armSpt, err := adal.NewServicePrincipalToken(*oauthConfig, clientID, clientSecret, env.ServiceManagementEndpoint) 57 if err != nil { 58 return nil, err 59 } 60 61 return getClient(env, subscriptionID, tenantID, armSpt), nil 62 } 63 64 func (az *AzureClient) EnsureResourceGroup(ctx context.Context, name, location string, managedBy *string) (resourceGroup *resources.Group, err error) { 65 var tags map[string]*string 66 group, err := az.groupsClient.Get(ctx, name) 67 if err == nil && group.Tags != nil { 68 tags = group.Tags 69 } else { 70 tags = make(map[string]*string) 71 } 72 // Tags for correlating resource groups with prow jobs on testgrid 73 tags["buildID"] = stringPointer(os.Getenv("BUILD_ID")) 74 tags["jobName"] = stringPointer(os.Getenv("JOB_NAME")) 75 tags["creationTimestamp"] = stringPointer(time.Now().UTC().Format(time.RFC3339)) 76 77 response, err := az.groupsClient.CreateOrUpdate(ctx, name, resources.Group{ 78 Name: &name, 79 Location: &location, 80 ManagedBy: managedBy, 81 Tags: tags, 82 }) 83 if err != nil { 84 return &response, err 85 } 86 87 return &response, nil 88 } 89 90 func (az *AzureClient) DeleteResourceGroup(ctx context.Context, groupName string) error { 91 _, err := az.groupsClient.Get(ctx, groupName) 92 if err == nil { 93 future, err := az.groupsClient.Delete(ctx, groupName) 94 if err != nil { 95 return fmt.Errorf("cannot delete resource group %v: %v", groupName, err) 96 } 97 err = future.WaitForCompletionRef(ctx, az.groupsClient.Client) 98 if err != nil { 99 // Skip the teardown errors because of https://github.com/Azure/go-autorest/issues/357 100 // TODO(feiskyer): fix the issue by upgrading go-autorest version >= v11.3.2. 101 log.Printf("Warning: failed to delete resource group %q with error %v", groupName, err) 102 } 103 } 104 return nil 105 } 106 107 func (az *AzureClient) EnsureVirtualMachine(ctx context.Context, groupName, location, vmName string) (vm compute.VirtualMachine, err error) { 108 nic, err := az.EnsureNIC(ctx, groupName, location, vmName+"-nic", vmName+"-vnet", vmName+"-subnet") 109 if err != nil { 110 return vm, err 111 } 112 113 future, err := az.vmClient.CreateOrUpdate( 114 ctx, 115 groupName, 116 vmName, 117 compute.VirtualMachine{ 118 Location: to.StringPtr(location), 119 VirtualMachineProperties: &compute.VirtualMachineProperties{ 120 HardwareProfile: &compute.HardwareProfile{ 121 VMSize: compute.VirtualMachineSizeTypesStandardDS2V2, 122 }, 123 StorageProfile: &compute.StorageProfile{ 124 ImageReference: &compute.ImageReference{ 125 Publisher: to.StringPtr("Canonical"), 126 Offer: to.StringPtr("UbuntuServer"), 127 Sku: to.StringPtr("16.04.0-LTS"), 128 Version: to.StringPtr("latest"), 129 }, 130 }, 131 OsProfile: &compute.OSProfile{ 132 ComputerName: to.StringPtr(vmName), 133 AdminUsername: to.StringPtr("azureuser"), 134 AdminPassword: to.StringPtr("Azureuser1234"), 135 }, 136 NetworkProfile: &compute.NetworkProfile{ 137 NetworkInterfaces: &[]compute.NetworkInterfaceReference{ 138 { 139 ID: nic.ID, 140 NetworkInterfaceReferenceProperties: &compute.NetworkInterfaceReferenceProperties{ 141 Primary: to.BoolPtr(true), 142 }, 143 }, 144 }, 145 }, 146 }, 147 }, 148 ) 149 if err != nil { 150 return vm, fmt.Errorf("cannot create vm: %v", err) 151 } 152 153 err = future.WaitForCompletionRef(ctx, az.vmClient.Client) 154 if err != nil { 155 return vm, fmt.Errorf("cannot get the vm create or update future response: %v", err) 156 } 157 158 return future.Result(az.vmClient) 159 } 160 161 func (az *AzureClient) EnsureNIC(ctx context.Context, groupName, location, nicName, vnetName, subnetName string) (nic network.Interface, err error) { 162 _, err = az.EnsureVirtualNetworkAndSubnet(ctx, groupName, location, vnetName, subnetName) 163 if err != nil { 164 return nic, err 165 } 166 167 subnet, err := az.GetVirtualNetworkSubnet(ctx, groupName, vnetName, subnetName) 168 if err != nil { 169 return nic, fmt.Errorf("cannot get subnet %s of virtual network %s in %s: %v", subnetName, vnetName, groupName, err) 170 } 171 172 future, err := az.nicClient.CreateOrUpdate( 173 ctx, 174 groupName, 175 nicName, 176 network.Interface{ 177 Name: to.StringPtr(nicName), 178 Location: to.StringPtr(location), 179 InterfacePropertiesFormat: &network.InterfacePropertiesFormat{ 180 IPConfigurations: &[]network.InterfaceIPConfiguration{ 181 { 182 Name: to.StringPtr("ipConfig1"), 183 InterfaceIPConfigurationPropertiesFormat: &network.InterfaceIPConfigurationPropertiesFormat{ 184 Subnet: &subnet, 185 PrivateIPAllocationMethod: network.Dynamic, 186 }, 187 }, 188 }, 189 }, 190 }, 191 ) 192 if err != nil { 193 return nic, fmt.Errorf("cannot create nic: %v", err) 194 } 195 196 err = future.WaitForCompletionRef(ctx, az.nicClient.Client) 197 if err != nil { 198 return nic, fmt.Errorf("cannot get nic create or update future response: %v", err) 199 } 200 201 return future.Result(az.nicClient) 202 } 203 204 func (az *AzureClient) EnsureVirtualNetworkAndSubnet(ctx context.Context, groupName, location, vnetName, subnetName string) (vnet network.VirtualNetwork, err error) { 205 future, err := az.vnetClient.CreateOrUpdate( 206 ctx, 207 groupName, 208 vnetName, 209 network.VirtualNetwork{ 210 Location: to.StringPtr(location), 211 VirtualNetworkPropertiesFormat: &network.VirtualNetworkPropertiesFormat{ 212 AddressSpace: &network.AddressSpace{ 213 AddressPrefixes: &[]string{"10.0.0.0/8"}, 214 }, 215 Subnets: &[]network.Subnet{ 216 { 217 Name: to.StringPtr(subnetName), 218 SubnetPropertiesFormat: &network.SubnetPropertiesFormat{ 219 AddressPrefix: to.StringPtr("10.0.0.0/16"), 220 }, 221 }, 222 }, 223 }, 224 }) 225 226 if err != nil { 227 return vnet, fmt.Errorf("cannot create virtual network: %v", err) 228 } 229 230 err = future.WaitForCompletionRef(ctx, az.vnetClient.Client) 231 if err != nil { 232 return vnet, fmt.Errorf("cannot get the vnet create or update future response: %v", err) 233 } 234 235 return future.Result(az.vnetClient) 236 } 237 238 func (az *AzureClient) GetVirtualNetworkSubnet(ctx context.Context, groupName, vnetName, subnetName string) (network.Subnet, error) { 239 return az.subnetsClient.Get(ctx, groupName, vnetName, subnetName, "") 240 } 241 242 func getOAuthConfig(env azure.Environment, subscriptionID, tenantID string) (*adal.OAuthConfig, error) { 243 oauthConfig, err := adal.NewOAuthConfig(env.ActiveDirectoryEndpoint, tenantID) 244 if err != nil { 245 return nil, err 246 } 247 248 return oauthConfig, nil 249 } 250 251 func getClient(env azure.Environment, subscriptionID, tenantID string, armSpt *adal.ServicePrincipalToken) *AzureClient { 252 c := &AzureClient{ 253 environment: env, 254 subscriptionID: subscriptionID, 255 groupsClient: resources.NewGroupsClientWithBaseURI(env.ResourceManagerEndpoint, subscriptionID), 256 vmClient: compute.NewVirtualMachinesClient(subscriptionID), 257 nicClient: network.NewInterfacesClient(subscriptionID), 258 subnetsClient: network.NewSubnetsClient(subscriptionID), 259 vnetClient: network.NewVirtualNetworksClient(subscriptionID), 260 } 261 262 authorizer := autorest.NewBearerAuthorizer(armSpt) 263 c.groupsClient.Authorizer = authorizer 264 c.vmClient.Authorizer = authorizer 265 c.nicClient.Authorizer = authorizer 266 c.subnetsClient.Authorizer = authorizer 267 c.vnetClient.Authorizer = authorizer 268 269 return c 270 } 271 272 func stringPointer(s string) *string { 273 return &s 274 }