yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/web_app.go (about) 1 // Copyright 2019 Yunion 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 "net/url" 20 "strings" 21 22 "yunion.io/x/log" 23 "yunion.io/x/pkg/errors" 24 25 "yunion.io/x/cloudmux/pkg/cloudprovider" 26 "yunion.io/x/cloudmux/pkg/multicloud" 27 ) 28 29 type SAppSite struct { 30 multicloud.SResourceBase 31 AzureTags 32 region *SRegion 33 appServicePlan *SAppServicePlan 34 35 Properties SAppSiteProperties 36 Id string 37 Name string 38 Kind string 39 Location string 40 Type string 41 42 stack *string 43 } 44 45 type SAppSiteProperties struct { 46 AvailabilityState string 47 DefaultHostName string 48 Enabled bool 49 EnabledHostNames []string 50 HostNameSslStates []SHostNameSslState 51 HostNames []string 52 HttpsOnly bool 53 OutboundIpAddresses string 54 ResourceGroup string 55 ServerFarmId string 56 SiteConfig SSiteConfig 57 State string 58 } 59 60 type SSiteConfig struct { 61 // TODO 62 } 63 64 type SHostNameSslState struct { 65 HostType string 66 Name string 67 SslState string 68 Thumbprint string 69 ToUpdate bool 70 VirtualIP string 71 } 72 73 func (r *SRegion) GetAppSites() ([]SAppSite, error) { 74 result := []SAppSite{} 75 resource := "Microsoft.Web/sites" 76 err := r.list(resource, url.Values{"api-version": []string{"2019-08-01"}}, &result) 77 if err != nil { 78 return nil, err 79 } 80 for i := range result { 81 result[i].region = r 82 } 83 return result, nil 84 } 85 86 func (r *SRegion) GetICloudApps() ([]cloudprovider.ICloudApp, error) { 87 ass, err := r.GetAppSites() 88 if err != nil { 89 return nil, err 90 } 91 apps := make([]cloudprovider.ICloudApp, 0, len(ass)) 92 for i := range ass { 93 apps = append(apps, &SApp{ 94 SAppSite: ass[i], 95 }) 96 } 97 return apps, nil 98 } 99 100 func (r *SRegion) GetICloudAppById(id string) (cloudprovider.ICloudApp, error) { 101 as, err := r.GetAppSite(id) 102 if err != nil { 103 return nil, err 104 } 105 return &SApp{ 106 SAppSite: *as, 107 }, nil 108 } 109 110 func (as *SAppSite) GetSlots() ([]SAppSite, error) { 111 result := []SAppSite{} 112 resource := fmt.Sprintf("subscriptions/%s/resourceGroups/%s/providers/Microsoft.Web/sites/%s/slots", as.region.client.subscriptionId, as.Properties.ResourceGroup, as.Name) 113 err := as.region.list(resource, url.Values{"api-version": []string{"2019-08-01"}}, &result) 114 if err != nil { 115 return nil, err 116 } 117 return result, nil 118 } 119 120 func (r *SRegion) GetAppSite(siteId string) (*SAppSite, error) { 121 as := &SAppSite{region: r} 122 params := url.Values{"api-version": []string{"2019-08-01"}} 123 return as, r.get(siteId, params, as) 124 } 125 126 func (as *SAppSite) GetAppServicePlan() (*SAppServicePlan, error) { 127 if as.appServicePlan != nil { 128 return as.appServicePlan, nil 129 } 130 plan, err := as.region.GetAppServicePlanWithCache(as.Properties.ServerFarmId) 131 if err != nil { 132 return nil, errors.Wrap(err, "unable to get AppServicePlan") 133 } 134 as.appServicePlan = plan 135 return plan, nil 136 } 137 138 type SDeployment struct { 139 ID string 140 Name string 141 Kind string 142 Type string 143 Properties SDeploymentProperties 144 } 145 146 type SDeploymentProperties struct { 147 Active bool 148 Author string 149 AuthorEmail string 150 Deployer string 151 Details string 152 EndTime string 153 Message string 154 StartTime string 155 Status string 156 } 157 158 func (as *SAppSite) GetDeployments() ([]SDeployment, error) { 159 result := []SDeployment{} 160 resource := fmt.Sprintf("subscriptions/%s/resourceGroups/%s/providers/Microsoft.Web/sites/%s/deployments", as.region.client._subscriptionId(), as.Properties.ResourceGroup, as.Name) 161 err := as.region.client.list(resource, url.Values{"api-version": []string{"2019-08-01"}}, &result) 162 if err != nil { 163 return nil, err 164 } 165 return result, nil 166 } 167 168 type SStringDictionary struct { 169 Id string 170 Kind string 171 Name string 172 Type string 173 Properties map[string]string 174 } 175 176 func (as *SAppSite) GetStack() (string, error) { 177 if as.stack != nil { 178 return *as.stack, nil 179 } 180 // result := SStringDictionary{} 181 resource := fmt.Sprintf("subscriptions/%s/resourceGroups/%s/providers/Microsoft.Web/sites/%s/config/metadata", as.region.client.subscriptionId, as.Properties.ResourceGroup, as.Name) 182 183 params := url.Values{} 184 params.Set("api-version", "2019-08-01") 185 path := resource + "/list" 186 response, err := as.region.client.jsonRequest("POST", path, nil, params, true) 187 if err != nil { 188 return "", err 189 } 190 stack, err := response.GetString("properties", "CURRENT_STACK") 191 if err != nil { 192 return "", errors.Wrapf(err, "unable to parse response correctly, response: %s", response) 193 } 194 as.stack = &stack 195 return stack, nil 196 } 197 198 func (as *SAppSite) GetId() string { 199 return as.Id 200 } 201 202 func (as *SAppSite) GetName() string { 203 return as.Name 204 } 205 206 func (as *SAppSite) GetGlobalId() string { 207 return strings.ToLower(as.Id) 208 } 209 210 func (as *SAppSite) GetStatus() string { 211 return "ready" 212 } 213 214 func (as *SAppSite) GetProjectId() string { 215 return strings.ToLower(as.Properties.ResourceGroup) 216 } 217 218 type SApp struct { 219 SAppSite 220 } 221 222 type SAppEnvironment struct { 223 multicloud.SResourceBase 224 AzureTags 225 SAppSite 226 } 227 228 func (ae *SAppEnvironment) GetInstanceType() (string, error) { 229 asp, err := ae.SAppSite.GetAppServicePlan() 230 if err != nil { 231 return "", err 232 } 233 return asp.Sku.Name, nil 234 } 235 236 func (ae *SAppEnvironment) GetInstanceNumber() (int, error) { 237 asp, err := ae.SAppSite.GetAppServicePlan() 238 if err != nil { 239 return 0, err 240 } 241 return asp.Sku.Capacity, nil 242 } 243 244 func (a *SApp) GetEnvironments() ([]cloudprovider.ICloudAppEnvironment, error) { 245 sites, err := a.SAppSite.GetSlots() 246 if err != nil { 247 return nil, err 248 } 249 aes := make([]cloudprovider.ICloudAppEnvironment, 0, len(sites)+1) 250 aes = append(aes, &SAppEnvironment{ 251 SAppSite: a.SAppSite, 252 }) 253 for i := range sites { 254 sites[i].region = a.region 255 aes = append(aes, &SAppEnvironment{ 256 SAppSite: sites[i], 257 }) 258 } 259 return aes, nil 260 } 261 262 var techStacks = map[string]string{ 263 "dotnet": ".NET", 264 "dotnetcore": ".NET Core", 265 "aspdotnet": "ASP.NET", 266 "node": "Node", 267 "python": "Python", 268 "php": "PHP", 269 "ruby": "Ruby", 270 "java": "Java", 271 "javacontainers": "Jave Containers", 272 } 273 274 func (a *SApp) GetTechStack() string { 275 if strings.Contains(a.SAppSite.Kind, "container") { 276 return "Docker container" 277 } 278 stack, err := a.GetStack() 279 if err != nil { 280 log.Errorf("unable to GetStack: %v", err) 281 } 282 if s, ok := techStacks[stack]; ok { 283 return s 284 } 285 return stack 286 } 287 288 func (a *SApp) GetType() string { 289 return "web" 290 } 291 292 func (a *SApp) GetKind() string { 293 return a.Kind 294 } 295 296 func (a *SApp) GetOsType() cloudprovider.TOsType { 297 if strings.Contains(a.Kind, "linux") { 298 return cloudprovider.OsTypeLinux 299 } 300 return cloudprovider.OsTypeWindows 301 } 302 303 func (self *SApp) SetTags(tags map[string]string, replace bool) error { 304 if !replace { 305 for k, v := range self.Tags { 306 if _, ok := tags[k]; !ok { 307 tags[k] = v 308 } 309 } 310 } 311 _, err := self.region.client.SetTags(self.Id, tags) 312 if err != nil { 313 return errors.Wrapf(err, "SetTags") 314 } 315 return nil 316 }