github.com/coreos/mantle@v0.13.0/platform/api/azure/api.go (about) 1 // Copyright 2016 CoreOS, Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package azure 16 17 import ( 18 "fmt" 19 "math/rand" 20 "os" 21 "os/user" 22 "path/filepath" 23 "strings" 24 "time" 25 26 "github.com/Azure/azure-sdk-for-go/arm/compute" 27 "github.com/Azure/azure-sdk-for-go/arm/network" 28 "github.com/Azure/azure-sdk-for-go/arm/resources/resources" 29 armStorage "github.com/Azure/azure-sdk-for-go/arm/storage" 30 "github.com/Azure/azure-sdk-for-go/management" 31 "github.com/Azure/azure-sdk-for-go/storage" 32 "github.com/Azure/go-autorest/autorest/azure/auth" 33 "github.com/coreos/pkg/capnslog" 34 35 internalAuth "github.com/coreos/mantle/auth" 36 ) 37 38 var ( 39 plog = capnslog.NewPackageLogger("github.com/coreos/mantle", "platform/api/azure") 40 ) 41 42 type API struct { 43 client management.Client 44 rgClient resources.GroupsClient 45 imgClient compute.ImagesClient 46 compClient compute.VirtualMachinesClient 47 netClient network.VirtualNetworksClient 48 subClient network.SubnetsClient 49 ipClient network.PublicIPAddressesClient 50 intClient network.InterfacesClient 51 accClient armStorage.AccountsClient 52 opts *Options 53 } 54 55 // New creates a new Azure client. If no publish settings file is provided or 56 // can't be parsed, an anonymous client is created. 57 func New(opts *Options) (*API, error) { 58 conf := management.DefaultConfig() 59 conf.APIVersion = "2015-04-01" 60 61 if opts.ManagementURL != "" { 62 conf.ManagementURL = opts.ManagementURL 63 } 64 65 if opts.StorageEndpointSuffix == "" { 66 opts.StorageEndpointSuffix = storage.DefaultBaseURL 67 } 68 69 profiles, err := internalAuth.ReadAzureProfile(opts.AzureProfile) 70 if err != nil { 71 return nil, fmt.Errorf("couldn't read Azure profile: %v", err) 72 } 73 74 subOpts := profiles.SubscriptionOptions(opts.AzureSubscription) 75 if subOpts == nil { 76 return nil, fmt.Errorf("Azure subscription named %q doesn't exist in %q", opts.AzureSubscription, opts.AzureProfile) 77 } 78 79 if os.Getenv("AZURE_AUTH_LOCATION") == "" { 80 if opts.AzureAuthLocation == "" { 81 user, err := user.Current() 82 if err != nil { 83 return nil, err 84 } 85 opts.AzureAuthLocation = filepath.Join(user.HomeDir, internalAuth.AzureAuthPath) 86 } 87 // TODO: Move to Flight once built to allow proper unsetting 88 os.Setenv("AZURE_AUTH_LOCATION", opts.AzureAuthLocation) 89 } 90 91 if opts.SubscriptionID == "" { 92 opts.SubscriptionID = subOpts.SubscriptionID 93 } 94 95 if opts.SubscriptionName == "" { 96 opts.SubscriptionName = subOpts.SubscriptionName 97 } 98 99 if opts.ManagementURL == "" { 100 opts.ManagementURL = subOpts.ManagementURL 101 } 102 103 if opts.ManagementCertificate == nil { 104 opts.ManagementCertificate = subOpts.ManagementCertificate 105 } 106 107 if opts.StorageEndpointSuffix == "" { 108 opts.StorageEndpointSuffix = subOpts.StorageEndpointSuffix 109 } 110 111 client, err := management.NewClientFromConfig(opts.SubscriptionID, opts.ManagementCertificate, conf) 112 if err != nil { 113 return nil, fmt.Errorf("failed to create azure client: %v", err) 114 } 115 116 api := &API{ 117 client: client, 118 opts: opts, 119 } 120 121 err = api.resolveImage() 122 if err != nil { 123 return nil, fmt.Errorf("failed to resolve image: %v", err) 124 } 125 126 return api, nil 127 } 128 129 func (a *API) SetupClients() error { 130 auther, err := auth.GetClientSetup(resources.DefaultBaseURI) 131 if err != nil { 132 return err 133 } 134 a.rgClient = resources.NewGroupsClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 135 a.rgClient.Authorizer = auther 136 137 auther, err = auth.GetClientSetup(compute.DefaultBaseURI) 138 if err != nil { 139 return err 140 } 141 a.imgClient = compute.NewImagesClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 142 a.imgClient.Authorizer = auther 143 a.compClient = compute.NewVirtualMachinesClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 144 a.compClient.Authorizer = auther 145 146 auther, err = auth.GetClientSetup(network.DefaultBaseURI) 147 if err != nil { 148 return err 149 } 150 a.netClient = network.NewVirtualNetworksClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 151 a.netClient.Authorizer = auther 152 a.subClient = network.NewSubnetsClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 153 a.subClient.Authorizer = auther 154 a.ipClient = network.NewPublicIPAddressesClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 155 a.ipClient.Authorizer = auther 156 a.intClient = network.NewInterfacesClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 157 a.intClient.Authorizer = auther 158 159 auther, err = auth.GetClientSetup(armStorage.DefaultBaseURI) 160 if err != nil { 161 return err 162 } 163 a.accClient = armStorage.NewAccountsClientWithBaseURI(auther.BaseURI, auther.SubscriptionID) 164 a.accClient.Authorizer = auther 165 166 return nil 167 } 168 169 func randomName(prefix string) string { 170 b := make([]byte, 5) 171 rand.Read(b) 172 return fmt.Sprintf("%s-%x", prefix, b) 173 } 174 175 func (a *API) GC(gracePeriod time.Duration) error { 176 durationAgo := time.Now().Add(-1 * gracePeriod) 177 178 listGroups, err := a.ListResourceGroups("") 179 if err != nil { 180 return fmt.Errorf("listing resource groups: %v", err) 181 } 182 183 for _, l := range *listGroups.Value { 184 if strings.HasPrefix(*l.Name, "kola-cluster") { 185 createdAt := *(*l.Tags)["createdAt"] 186 timeCreated, err := time.Parse(time.RFC3339, createdAt) 187 if err != nil { 188 return fmt.Errorf("error parsing time: %v", err) 189 } 190 if !timeCreated.After(durationAgo) { 191 if err = a.TerminateResourceGroup(*l.Name); err != nil { 192 return err 193 } 194 } 195 } 196 } 197 198 return nil 199 }