yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/aws/imageowners.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 aws 16 17 import ( 18 "fmt" 19 "regexp" 20 "strconv" 21 "strings" 22 23 "yunion.io/x/pkg/util/regutils" 24 25 "yunion.io/x/cloudmux/pkg/cloudprovider" 26 ) 27 28 func getSystemOwnerIds() []string { 29 keys := make([]string, len(awsImagePublishers)) 30 idx := 0 31 for key := range awsImagePublishers { 32 keys[idx] = key 33 idx += 1 34 } 35 return keys 36 } 37 38 func stringArray2StringPtrArray(arr []string) []*string { 39 ret := make([]*string, len(arr)) 40 for i := range arr { 41 ret[i] = &arr[i] 42 } 43 return ret 44 } 45 46 func imageOwnerTypes2Strings(owners []TImageOwnerType, rawIds []string) []*string { 47 ownerIds := make([]string, 0) 48 for i := range owners { 49 switch owners[i] { 50 case ImageOwnerTypeSelf: 51 ownerIds = append(ownerIds, "self") 52 case ImageOwnerTypeSystem: 53 sysOwnerIds := getSystemOwnerIds() 54 ownerIds = append(ownerIds, sysOwnerIds...) 55 } 56 } 57 ownerIds = append(ownerIds, rawIds...) 58 return stringArray2StringPtrArray(ownerIds) 59 } 60 61 type SAWSImagePublisherInfo struct { 62 GetOSType func(image SImage) string 63 GetOSDist func(image SImage) string 64 GetOSVersion func(image SImage) string 65 GetOSBuildID func(image SImage) string 66 CompareBuilds func(v1, v2 string) int 67 } 68 69 var rhel = SAWSImagePublisherInfo{ 70 GetOSType: func(image SImage) string { 71 return "Linux" 72 }, 73 GetOSDist: func(image SImage) string { 74 return "RHEL" 75 }, 76 GetOSVersion: func(image SImage) string { 77 parts := strings.Split(image.ImageName, "-") 78 if len(parts) >= 2 { 79 parts = strings.Split(parts[1], "_") 80 return parts[0] 81 } 82 return "" 83 }, 84 GetOSBuildID: func(image SImage) string { 85 parts := strings.Split(image.ImageName, "-") 86 if len(parts) >= 2 { 87 return parts[2] 88 } 89 return "" 90 }, 91 } 92 93 var ( 94 debianDatePattern = regexp.MustCompile(`-\d{4}-\d{2}-\d{2}-`) 95 ) 96 97 var debian = SAWSImagePublisherInfo{ 98 GetOSType: func(image SImage) string { 99 return "Linux" 100 }, 101 GetOSDist: func(image SImage) string { 102 return "Debian" 103 }, 104 GetOSVersion: func(image SImage) string { 105 parts := strings.Split(image.ImageName, "-") 106 if len(parts) >= 5 { 107 return parts[1] 108 } 109 return "" 110 }, 111 GetOSBuildID: func(image SImage) string { 112 dateStr := debianDatePattern.FindString(image.ImageName) 113 if len(dateStr) > 2 { 114 return dateStr[1 : len(dateStr)-1] 115 } 116 return "" 117 }, 118 } 119 120 var ( 121 centosDatePattern = regexp.MustCompile(`\s+\d{4,8}(_\d+)?`) 122 ) 123 124 var centos = SAWSImagePublisherInfo{ 125 GetOSType: func(image SImage) string { 126 return "Linux" 127 }, 128 GetOSDist: func(image SImage) string { 129 if strings.Index(image.ImageName, "Atomic") > 0 { 130 return "CentOS Atomic" 131 } else { 132 return "CentOS" 133 } 134 }, 135 GetOSVersion: func(image SImage) string { 136 parts := strings.Split(image.ImageName, " ") 137 if strings.Index(image.ImageName, "Atomic") > 0 { 138 if regutils.MatchInteger(parts[3]) { 139 return parts[3] 140 } else { 141 return "7" 142 } 143 } else if strings.HasPrefix(image.ImageName, "CentOS Linux ") { 144 return parts[2] 145 } else { 146 return parts[1] 147 } 148 }, 149 GetOSBuildID: func(image SImage) string { 150 build := centosDatePattern.FindString(image.ImageName) 151 build = strings.TrimSpace(build) 152 if strings.HasPrefix(build, "201") { 153 build = build[2:] 154 } 155 return build 156 }, 157 } 158 159 var ubuntuReleases = map[string]string{ 160 "warty": "4.10", 161 "hoary": "5.04", 162 "breezy": "5.10", 163 "dapper": "6.06", 164 "edgy": "6.10", 165 "feisty": "7.04", 166 "gutsy": "7.10", 167 "hardy": "8.04", 168 "intrepid": "8.10", 169 "jaunty": "9.04", 170 "karmic": "9.10", 171 "lucid": "10.04", 172 "maverick": "10.10", 173 "natty": "11.04", 174 "oneiric": "11.10", 175 "precise": "12.04", 176 "quantal": "12.10", 177 "raring": "13.04", 178 "saucy": "13.10", 179 "trusty": "14.04", 180 "utopic": "14.10", 181 "vivid": "15.04", 182 "wily": "15.10", 183 "xenial": "16.04", 184 "yakkety": "16.10", 185 "zesty": "17.04", 186 "artful": "17.10", 187 "bionic": "18.04", 188 "cosmic": "18.10", 189 "disco": "19.04", 190 } 191 192 var ubuntuReleasePattern = regexp.MustCompile(`-\d+\.\d+-`) 193 194 var ubuntu = SAWSImagePublisherInfo{ 195 GetOSType: func(image SImage) string { 196 return "Linux" 197 }, 198 GetOSDist: func(image SImage) string { 199 if strings.HasPrefix(image.ImageName, "ubuntu-minimal/") { 200 return "Ubuntu Minimal" 201 } 202 if strings.HasPrefix(image.ImageName, "ubuntu/") { 203 return "Ubuntu" 204 } 205 if strings.HasPrefix(image.ImageName, "ubuntu-rolling-") || strings.HasPrefix(image.ImageName, "ubuntu-core") || strings.Index(image.ImageName, "core-edge") > 0 { 206 return "Ubuntu Core" 207 } 208 return "Ubuntu" 209 }, 210 GetOSVersion: func(image SImage) string { 211 relStr := ubuntuReleasePattern.FindString(image.ImageName) 212 if len(relStr) > 2 { 213 return relStr[1 : len(relStr)-1] 214 } 215 parts := strings.Split(image.ImageName, "/") 216 if len(parts) >= 4 { 217 parts = strings.Split(parts[3], "-") 218 if len(parts) >= 2 { 219 relName := strings.ToLower(parts[1]) 220 if _, ok := ubuntuReleases[relName]; ok { 221 return ubuntuReleases[relName] 222 } else { 223 return relName 224 } 225 } 226 } 227 if strings.HasPrefix(image.ImageName, "ubuntu-rolling-") { 228 parts := strings.Split(image.ImageName, "-") 229 if len(parts) > 3 { 230 return strings.ToLower(parts[2]) 231 } 232 } 233 return "" 234 }, 235 GetOSBuildID: func(image SImage) string { 236 parts := strings.Split(image.ImageName, "-") 237 return parts[len(parts)-1] 238 }, 239 } 240 241 var ( 242 SUSE_SLES = regexp.MustCompile(`suse-sles-\d+-v?\d+-`) 243 SUSE_SLES_SP = regexp.MustCompile(`suse-sles-\d+-sp\d+-v?\d+-`) 244 SUSE_SLES_RIGHTLINK = regexp.MustCompile(`suse-sles-\d+-rightscale-v?\d+-`) 245 SUSE_SLES_RIGHTLINK_SP = regexp.MustCompile(`suse-sles-\d+-sp\d+-rightscale-v?\d+-`) 246 SUSE_SLES_SAPCAL = regexp.MustCompile(`suse-sles-\d+-sapcal-v?\d+-`) 247 SUSE_SLES_SAPCAL_SP = regexp.MustCompile(`suse-sles-\d+-sp\d+-sapcal-v?\d+-`) 248 SUSE_SLES_BYOS = regexp.MustCompile(`suse-sles-\d+-byos-v?\d+-`) 249 SUSE_SLES_BYOS_SP = regexp.MustCompile(`suse-sles-\d+-sp\d+-byos-v?\d+-`) 250 SUSE_SLES_SAP = regexp.MustCompile(`suse-sles-sap-\d+-v\d+-`) 251 SUSE_SLES_SAP_SP = regexp.MustCompile(`suse-sles-sap-\d+-sp\d+-v\d+-`) 252 SUSE_SLES_SAP_BYOS = regexp.MustCompile(`suse-sles-sap-\d+-byos-v?\d+-`) 253 SUSE_SLES_SAP_BYOS_SP = regexp.MustCompile(`suse-sles-sap-\d+-sp\d+-byos-v?\d+-`) 254 255 SUSE_CAASP_CLUSTER_BYOS = regexp.MustCompile(`suse-caasp-\d+-\d+-cluster-byos-v?\d+-`) 256 SUSE_CAASP_ADMIN_BYOS = regexp.MustCompile(`suse-caasp-\d+-\d+-admin-byos-v?\d+-`) 257 258 SUSE_MANAGER_SERVER_BYOS = regexp.MustCompile(`suse-manager-\d+-\d+-server-byos-v?\d+-`) 259 SUSE_MANAGER_PROXY_BYOS = regexp.MustCompile(`suse-manager-\d+-\d+-proxy-byos-v?\d+-`) 260 ) 261 262 func getBuildId(ver string) string { 263 if ver[0] == 'v' { 264 return ver[1:] 265 } else { 266 return ver 267 } 268 } 269 270 var suse = SAWSImagePublisherInfo{ 271 GetOSType: func(image SImage) string { 272 return "Linux" 273 }, 274 GetOSDist: func(image SImage) string { 275 switch { 276 case SUSE_SLES.MatchString(image.ImageName), SUSE_SLES_SP.MatchString(image.ImageName): 277 return "SUSE Linux Enterpise Server" 278 case SUSE_SLES_RIGHTLINK.MatchString(image.ImageName), SUSE_SLES_RIGHTLINK_SP.MatchString(image.ImageName): 279 return "SUSE Linux Enterpise Server with RightLink" 280 case SUSE_SLES_SAPCAL.MatchString(image.ImageName), SUSE_SLES_SAPCAL_SP.MatchString(image.ImageName): 281 return "SUSE Linux Enterpise Server for SAP CAL" 282 case SUSE_SLES_BYOS.MatchString(image.ImageName), SUSE_SLES_BYOS_SP.MatchString(image.ImageName): 283 return "SUSE Linux Enterpise Server BYOS" 284 case SUSE_SLES_SAP.MatchString(image.ImageName), SUSE_SLES_SAP_SP.MatchString(image.ImageName): 285 return "SUSE Linux Enterpise Server for SAP Application" 286 case SUSE_SLES_SAP_BYOS.MatchString(image.ImageName), SUSE_SLES_SAP_BYOS_SP.MatchString(image.ImageName): 287 return "SUSE Linux Enterpise Server for SAP Application BYOS" 288 case SUSE_CAASP_CLUSTER_BYOS.MatchString(image.ImageName): 289 return "SUSE CaaSP Cluster Node" 290 case SUSE_CAASP_ADMIN_BYOS.MatchString(image.ImageName): 291 return "SUSE CaaSP Admin Node" 292 case SUSE_MANAGER_SERVER_BYOS.MatchString(image.ImageName): 293 return "SUSE Manager Server" 294 case SUSE_MANAGER_PROXY_BYOS.MatchString(image.ImageName): 295 return "SUSE Manager Proxy" 296 } 297 return "SUSE" 298 }, 299 GetOSVersion: func(image SImage) string { 300 parts := strings.Split(image.ImageName, "-") 301 switch { 302 case SUSE_SLES.MatchString(image.ImageName): 303 return parts[2] 304 case SUSE_SLES_SP.MatchString(image.ImageName): 305 return fmt.Sprintf("%s.%s", parts[2], parts[3][2:]) 306 case SUSE_SLES_RIGHTLINK.MatchString(image.ImageName): 307 return parts[2] 308 case SUSE_SLES_RIGHTLINK_SP.MatchString(image.ImageName): 309 return fmt.Sprintf("%s.%s", parts[2], parts[3][2:]) 310 case SUSE_SLES_SAPCAL.MatchString(image.ImageName): 311 return parts[2] 312 case SUSE_SLES_SAPCAL_SP.MatchString(image.ImageName): 313 return fmt.Sprintf("%s.%s", parts[2], parts[3][2:]) 314 case SUSE_SLES_BYOS.MatchString(image.ImageName): 315 return parts[2] 316 case SUSE_SLES_BYOS_SP.MatchString(image.ImageName): 317 return fmt.Sprintf("%s.%s", parts[2], parts[3][2:]) 318 case SUSE_SLES_SAP.MatchString(image.ImageName): 319 return parts[3] 320 case SUSE_SLES_SAP_SP.MatchString(image.ImageName): 321 return fmt.Sprintf("%s.%s", parts[3], parts[4][2:]) 322 case SUSE_SLES_SAP_BYOS.MatchString(image.ImageName): 323 return parts[3] 324 case SUSE_SLES_SAP_BYOS_SP.MatchString(image.ImageName): 325 return fmt.Sprintf("%s.%s", parts[3], parts[4][2:]) 326 case SUSE_CAASP_CLUSTER_BYOS.MatchString(image.ImageName): 327 return fmt.Sprintf("%s.%s", parts[2], parts[3]) 328 case SUSE_CAASP_ADMIN_BYOS.MatchString(image.ImageName): 329 return fmt.Sprintf("%s.%s", parts[2], parts[3]) 330 case SUSE_MANAGER_SERVER_BYOS.MatchString(image.ImageName): 331 return fmt.Sprintf("%s.%s", parts[2], parts[3]) 332 case SUSE_MANAGER_PROXY_BYOS.MatchString(image.ImageName): 333 return fmt.Sprintf("%s.%s", parts[2], parts[3]) 334 } 335 return "" 336 }, 337 GetOSBuildID: func(image SImage) string { 338 parts := strings.Split(image.ImageName, "-") 339 switch { 340 case SUSE_SLES.MatchString(image.ImageName): 341 return getBuildId(parts[3]) 342 case SUSE_SLES_SP.MatchString(image.ImageName): 343 return getBuildId(parts[4]) 344 case SUSE_SLES_RIGHTLINK.MatchString(image.ImageName): 345 return getBuildId(parts[4]) 346 case SUSE_SLES_RIGHTLINK_SP.MatchString(image.ImageName): 347 return getBuildId(parts[5]) 348 case SUSE_SLES_SAPCAL.MatchString(image.ImageName): 349 return getBuildId(parts[4]) 350 case SUSE_SLES_SAPCAL_SP.MatchString(image.ImageName): 351 return getBuildId(parts[5]) 352 case SUSE_SLES_BYOS.MatchString(image.ImageName): 353 return getBuildId(parts[4]) 354 case SUSE_SLES_BYOS_SP.MatchString(image.ImageName): 355 return getBuildId(parts[5]) 356 case SUSE_SLES_SAP.MatchString(image.ImageName): 357 return getBuildId(parts[4]) 358 case SUSE_SLES_SAP_SP.MatchString(image.ImageName): 359 return getBuildId(parts[5]) 360 case SUSE_SLES_SAP_BYOS.MatchString(image.ImageName): 361 return getBuildId(parts[5]) 362 case SUSE_SLES_SAP_BYOS_SP.MatchString(image.ImageName): 363 return getBuildId(parts[6]) 364 case SUSE_CAASP_CLUSTER_BYOS.MatchString(image.ImageName): 365 return getBuildId(parts[6]) 366 case SUSE_CAASP_ADMIN_BYOS.MatchString(image.ImageName): 367 return getBuildId(parts[6]) 368 case SUSE_MANAGER_SERVER_BYOS.MatchString(image.ImageName): 369 return getBuildId(parts[6]) 370 case SUSE_MANAGER_PROXY_BYOS.MatchString(image.ImageName): 371 return getBuildId(parts[6]) 372 } 373 return "" 374 }, 375 } 376 377 var coreosVersionTable = map[string]int{ 378 "alpha": 0, 379 "beta": 1, 380 "stable": 2, 381 } 382 383 var coreos = SAWSImagePublisherInfo{ 384 GetOSType: func(image SImage) string { 385 return "Linux" 386 }, 387 GetOSDist: func(image SImage) string { 388 return "CoreOS" 389 }, 390 GetOSVersion: func(image SImage) string { 391 parts := strings.Split(image.ImageName, "-") 392 subparts := strings.Split(parts[2], ".") 393 return subparts[0] 394 }, 395 GetOSBuildID: func(image SImage) string { 396 parts := strings.Split(image.ImageName, "-") 397 return fmt.Sprintf("%s-%s", parts[1], parts[2]) 398 }, 399 CompareBuilds: func(v1, v2 string) int { 400 parts1 := strings.Split(v1, "-") 401 parts2 := strings.Split(v2, "-") 402 majorV1 := coreosVersionTable[parts1[0]] 403 majorV2 := coreosVersionTable[parts2[0]] 404 if majorV1 != majorV2 { 405 return majorV1 - majorV2 406 } 407 parts1 = strings.Split(parts1[1], ".") 408 parts2 = strings.Split(parts2[1], ".") 409 for i := 0; i < len(parts1) && i < len(parts2); i += 1 { 410 n1, _ := strconv.Atoi(parts1[i]) 411 n2, _ := strconv.Atoi(parts2[i]) 412 if n1 != n2 { 413 return n1 - n2 414 } 415 } 416 return len(parts1) - len(parts2) 417 }, 418 } 419 420 var ( 421 sqlServerPattern = regexp.MustCompile(`-SQL_(\d+)_(\w+)-`) 422 dotnetcorePattern = regexp.MustCompile(`-dotnetcore-`) 423 ) 424 425 var windowsServer = SAWSImagePublisherInfo{ 426 GetOSType: func(image SImage) string { 427 if strings.HasPrefix(image.ImageName, "ubuntu-") || strings.HasPrefix(image.ImageName, "amzn-ami-") || strings.HasPrefix(image.ImageName, "amzn2-ami-") { 428 return "Linux" 429 } else { 430 return "Windows" 431 } 432 }, 433 GetOSDist: func(image SImage) string { 434 osStr := "Windows Server" 435 if strings.HasPrefix(image.ImageName, "ubuntu-") { 436 osStr = "Ubuntu" 437 } else if strings.HasPrefix(image.ImageName, "amzn-ami-") || strings.HasPrefix(image.ImageName, "amzn2-ami-") { 438 osStr = "Amazon Linux" 439 } 440 apps := make([]string, 0) 441 matchApp := sqlServerPattern.FindStringSubmatch(image.ImageName) 442 if len(matchApp) > 0 { 443 apps = append(apps, fmt.Sprintf("SQL Server %s %s", matchApp[1], matchApp[2])) 444 } 445 if dotnetcorePattern.MatchString(image.ImageName) { 446 apps = append(apps, ".Net Core") 447 } 448 if len(apps) > 0 { 449 osStr = fmt.Sprintf("%s with %s", osStr, strings.Join(apps, " ")) 450 } 451 return osStr 452 }, 453 GetOSVersion: func(image SImage) string { 454 if strings.HasPrefix(image.ImageName, "ubuntu-") { 455 return ubuntu.GetOSVersion(image) 456 } 457 if strings.HasPrefix(image.ImageName, "amzn-ami-") || strings.HasPrefix(image.ImageName, "amzn2-ami-") { 458 return amazon.GetOSVersion(image) 459 } 460 parts := strings.Split(image.ImageName, "-") 461 return strings.Join(parts[1:len(parts)-1], " ") 462 }, 463 GetOSBuildID: func(image SImage) string { 464 if strings.HasPrefix(image.ImageName, "ubuntu-") { 465 return ubuntu.GetOSBuildID(image) 466 } 467 if strings.HasPrefix(image.ImageName, "amzn-ami-") || strings.HasPrefix(image.ImageName, "amzn2-ami-") { 468 return amazon.GetOSBuildID(image) 469 } 470 parts := strings.Split(image.ImageName, "-") 471 return parts[len(parts)-1] 472 }, 473 } 474 475 var ( 476 amazonVersionPattern = regexp.MustCompile(`-(\d{4})\.(\d{2})\.(rc-\d+|\d+)(\.(\d+))?`) 477 amazonVersionPattern2 = regexp.MustCompile(`-(\d{1,2})\.(\d{1,2})\.(\d{8})(\.(\d+))?`) 478 ) 479 480 var amazon = SAWSImagePublisherInfo{ 481 GetOSType: func(image SImage) string { 482 return "Linux" 483 }, 484 GetOSDist: func(image SImage) string { 485 if strings.HasPrefix(image.ImageName, "amzn-ami-minimal-") || strings.HasPrefix(image.ImageName, "amzn2-ami-minimal-") { 486 return "Amazon Linux Minimal" 487 } else { 488 return "Amazon Linux" 489 } 490 }, 491 GetOSVersion: func(image SImage) string { 492 verStrs := amazonVersionPattern2.FindStringSubmatch(image.ImageName) 493 if len(verStrs) > 3 { 494 return fmt.Sprintf("%s.%s.%s", verStrs[1], verStrs[2], verStrs[3][:6]) 495 } 496 verStrs = amazonVersionPattern.FindStringSubmatch(image.ImageName) 497 if len(verStrs) > 3 { 498 return fmt.Sprintf("%s.%s.%s", verStrs[1], verStrs[2], verStrs[3]) 499 } 500 return "" 501 }, 502 GetOSBuildID: func(image SImage) string { 503 verStrs := amazonVersionPattern2.FindStringSubmatch(image.ImageName) 504 if len(verStrs) > 5 && len(verStrs[5]) > 0 { 505 return fmt.Sprintf("%s.%s", verStrs[3], verStrs[5]) 506 } else if len(verStrs) > 3 { 507 return verStrs[3] 508 } 509 verStrs = amazonVersionPattern.FindStringSubmatch(image.ImageName) 510 if len(verStrs) > 5 { 511 return verStrs[5] 512 } 513 return "" 514 }, 515 } 516 517 var awsImagePublishers = map[string]SAWSImagePublisherInfo{ 518 "841258680906": rhel, // china 519 "309956199498": rhel, // international 520 "673060587306": debian, // china 521 "379101102735": debian, // international 522 "718707510307": centos, // china 523 "410186602215": centos, // international 524 "837727238323": ubuntu, // china 525 "099720109477": ubuntu, // internaltional 526 "841869936221": suse, // china 527 "013907871322": suse, // international 528 "280032941352": coreos, // china 529 "595879546273": coreos, // international 530 "016951021795": windowsServer, // china 531 "801119661308": windowsServer, // international 532 "141808717104": amazon, // china 533 "137112412989": amazon, // international 534 } 535 536 func getImageOSType(image SImage) string { 537 ownerInfo, ok := awsImagePublishers[image.OwnerId] 538 if ok { 539 return ownerInfo.GetOSType(image) 540 } 541 return image.OSType 542 } 543 544 func getImageOSDist(image SImage) string { 545 ownerInfo, ok := awsImagePublishers[image.OwnerId] 546 if ok { 547 return ownerInfo.GetOSDist(image) 548 } 549 return "" 550 } 551 552 func getImageOSVersion(image SImage) string { 553 ownerInfo, ok := awsImagePublishers[image.OwnerId] 554 if ok { 555 return ownerInfo.GetOSVersion(image) 556 } 557 return "" 558 } 559 560 func getImageOSBuildID(image SImage) string { 561 ownerInfo, ok := awsImagePublishers[image.OwnerId] 562 if ok { 563 return ownerInfo.GetOSBuildID(image) 564 } 565 return "" 566 } 567 568 func comapreImageBuildIds(ver1 string, img2 SImage) int { 569 ownerInfo, ok := awsImagePublishers[img2.OwnerId] 570 if ok && ownerInfo.CompareBuilds != nil { 571 return ownerInfo.CompareBuilds(ver1, img2.OSBuildId) 572 } 573 return strings.Compare(ver1, img2.OSBuildId) 574 } 575 576 func getImageType(image SImage) cloudprovider.TImageType { 577 _, ok := awsImagePublishers[image.OwnerId] 578 if ok { 579 return cloudprovider.ImageTypeSystem 580 } 581 if !image.Public { 582 return cloudprovider.ImageTypeCustomized 583 } 584 return cloudprovider.ImageTypeMarket 585 }