yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/objectstore/shell.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 objectstore 16 17 import ( 18 "context" 19 "fmt" 20 "io" 21 "mime" 22 "net/http" 23 "os" 24 "path/filepath" 25 "strings" 26 "time" 27 28 "yunion.io/x/pkg/errors" 29 30 "yunion.io/x/cloudmux/pkg/cloudprovider" 31 "yunion.io/x/onecloud/pkg/util/fileutils2" 32 "yunion.io/x/onecloud/pkg/util/printutils" 33 "yunion.io/x/onecloud/pkg/util/shellutils" 34 "yunion.io/x/onecloud/pkg/util/streamutils" 35 ) 36 37 type ObjectHeaderOptions struct { 38 CacheControl string `help:"Cache-Control"` 39 ContentType string `help:"Content-Type"` 40 ContentEncoding string `help:"Content-Encoding"` 41 ContentLanguage string `help:"Content-Language"` 42 ContentDisposition string `help:"Content-Disposition"` 43 ContentMD5 string `help:"Content-MD5"` 44 45 Meta []string `help:"header, common seperatored key and value, e.g. max-age:100"` 46 } 47 48 func (args ObjectHeaderOptions) Options2Header() http.Header { 49 meta := http.Header{} 50 for _, kv := range args.Meta { 51 parts := strings.Split(kv, ":") 52 if len(parts) == 2 { 53 key := strings.TrimSpace(parts[0]) 54 value := strings.TrimSpace(parts[1]) 55 if len(key) > 0 && len(value) > 0 { 56 meta.Add(key, value) 57 } 58 } 59 } 60 if len(args.CacheControl) > 0 { 61 meta.Set(cloudprovider.META_HEADER_CACHE_CONTROL, args.CacheControl) 62 } 63 if len(args.ContentType) > 0 { 64 meta.Set(cloudprovider.META_HEADER_CONTENT_TYPE, args.ContentType) 65 } 66 if len(args.ContentEncoding) > 0 { 67 meta.Set(cloudprovider.META_HEADER_CONTENT_ENCODING, args.ContentEncoding) 68 } 69 if len(args.ContentMD5) > 0 { 70 meta.Set(cloudprovider.META_HEADER_CONTENT_MD5, args.ContentMD5) 71 } 72 if len(args.ContentLanguage) > 0 { 73 meta.Set(cloudprovider.META_HEADER_CONTENT_LANGUAGE, args.ContentLanguage) 74 } 75 if len(args.ContentDisposition) > 0 { 76 meta.Set(cloudprovider.META_HEADER_CONTENT_DISPOSITION, args.ContentDisposition) 77 } 78 return meta 79 } 80 81 func printList(data interface{}, total, offset, limit int, columns []string) { 82 printutils.PrintInterfaceList(data, total, offset, limit, columns) 83 } 84 85 func printObject(obj interface{}) { 86 printutils.PrintInterfaceObject(obj) 87 } 88 89 func S3Shell() { 90 type BucketListOptions struct { 91 } 92 shellutils.R(&BucketListOptions{}, "bucket-list", "List all bucket", func(cli cloudprovider.ICloudRegion, args *BucketListOptions) error { 93 buckets, err := cli.GetIBuckets() 94 if err != nil { 95 return err 96 } 97 printutils.PrintGetterList(buckets, nil) 98 return nil 99 }) 100 101 type BucketCreateOptions struct { 102 NAME string `help:"name of bucket to create"` 103 Acl string `help:"ACL string" choices:"private|public-read|public-read-write"` 104 StorageClass string `help:"StorageClass"` 105 } 106 shellutils.R(&BucketCreateOptions{}, "bucket-create", "Create bucket", func(cli cloudprovider.ICloudRegion, args *BucketCreateOptions) error { 107 err := cli.CreateIBucket(args.NAME, args.StorageClass, args.Acl) 108 if err != nil { 109 return err 110 } 111 return nil 112 }) 113 114 type BucketAclOptions struct { 115 BUCKET string `help:"name of bucket"` 116 ACL string `help:"ACL string" choices:"private|public-read|public-read-write"` 117 } 118 shellutils.R(&BucketAclOptions{}, "bucket-set-acl", "Create bucket", func(cli cloudprovider.ICloudRegion, args *BucketAclOptions) error { 119 bucket, err := cli.GetIBucketById(args.BUCKET) 120 if err != nil { 121 return err 122 } 123 err = bucket.SetAcl(cloudprovider.TBucketACLType(args.ACL)) 124 if err != nil { 125 return err 126 } 127 return nil 128 }) 129 130 type BucketDeleteOptions struct { 131 NAME string `help:"name of bucket to delete"` 132 } 133 shellutils.R(&BucketDeleteOptions{}, "bucket-delete", "Delete bucket", func(cli cloudprovider.ICloudRegion, args *BucketDeleteOptions) error { 134 err := cli.DeleteIBucket(args.NAME) 135 if err != nil { 136 return err 137 } 138 return nil 139 }) 140 141 type BucketLimitOptions struct { 142 NAME string `help:"name of bucket to set limit"` 143 SizeGB int `help:"limit of volumes in GB"` 144 Objects int `help:"limit of object count"` 145 Off bool `help:"Turn off limit"` 146 } 147 shellutils.R(&BucketLimitOptions{}, "bucket-set-limit", "Set bucket limit", func(cli cloudprovider.ICloudRegion, args *BucketLimitOptions) error { 148 bucket, err := cli.GetIBucketByName(args.NAME) 149 if err != nil { 150 return err 151 } 152 if args.Off { 153 err = bucket.SetLimit(cloudprovider.SBucketStats{}) 154 } else { 155 fmt.Println("set limit") 156 err = bucket.SetLimit(cloudprovider.SBucketStats{SizeBytes: int64(args.SizeGB * 1000 * 1000 * 1000), ObjectCount: args.Objects}) 157 } 158 if err != nil { 159 return err 160 } 161 return nil 162 }) 163 164 type BucketExistOptions struct { 165 NAME string `help:"name of bucket to delete"` 166 } 167 shellutils.R(&BucketExistOptions{}, "bucket-exist", "Test existence of a bucket", func(cli cloudprovider.ICloudRegion, args *BucketExistOptions) error { 168 exist, err := cli.IBucketExist(args.NAME) 169 if err != nil { 170 return err 171 } 172 fmt.Printf("Exist: %v\n", exist) 173 return nil 174 }) 175 176 type BucketObjectsOptions struct { 177 BUCKET string `help:"name of bucket to list objects"` 178 Prefix string `help:"prefix"` 179 Marker string `help:"marker"` 180 Demiliter string `help:"delimiter"` 181 Max int `help:"Max count"` 182 } 183 shellutils.R(&BucketObjectsOptions{}, "bucket-object", "List objects in a bucket", func(cli cloudprovider.ICloudRegion, args *BucketObjectsOptions) error { 184 bucket, err := cli.GetIBucketById(args.BUCKET) 185 if err != nil { 186 return err 187 } 188 result, err := bucket.ListObjects(args.Prefix, args.Marker, args.Demiliter, args.Max) 189 if err != nil { 190 return err 191 } 192 if result.IsTruncated { 193 fmt.Printf("NextMarker: %s IsTruncated: %v\n", result.NextMarker, result.IsTruncated) 194 } 195 fmt.Println("Common prefixes:") 196 printutils.PrintGetterList(result.CommonPrefixes, []string{"key", "size_bytes"}) 197 fmt.Println("Objects:") 198 printutils.PrintGetterList(result.Objects, []string{"key", "size_bytes"}) 199 return nil 200 }) 201 202 type BucketListObjectsOptions struct { 203 BUCKET string `help:"name of bucket to list objects"` 204 Prefix string `help:"prefix"` 205 Limit int `help:"limit per page request" default:"20"` 206 Marker string `help:"offset marker"` 207 } 208 shellutils.R(&BucketListObjectsOptions{}, "bucket-list-object", "List objects in a bucket", func(cli cloudprovider.ICloudRegion, args *BucketListObjectsOptions) error { 209 bucket, err := cli.GetIBucketById(args.BUCKET) 210 if err != nil { 211 return err 212 } 213 objects, marker, err := cloudprovider.GetPagedObjects(bucket, args.Prefix, true, args.Marker, args.Limit) 214 if err != nil { 215 return err 216 } 217 printutils.PrintGetterList(objects, []string{"key", "size_bytes"}) 218 if len(marker) > 0 { 219 fmt.Println("Next marker:", marker) 220 } 221 return nil 222 }) 223 224 shellutils.R(&BucketListObjectsOptions{}, "bucket-dir-object", "List objects in a bucket like directory", func(cli cloudprovider.ICloudRegion, args *BucketListObjectsOptions) error { 225 bucket, err := cli.GetIBucketById(args.BUCKET) 226 if err != nil { 227 return err 228 } 229 objects, marker, err := cloudprovider.GetPagedObjects(bucket, args.Prefix, false, args.Marker, args.Limit) 230 if err != nil { 231 return err 232 } 233 printutils.PrintGetterList(objects, []string{"key", "size_bytes"}) 234 if len(marker) > 0 { 235 fmt.Println("Next marker:", marker) 236 } 237 return nil 238 }) 239 240 type BucketMakrdirOptions struct { 241 BUCKET string `help:"name of bucket to put object"` 242 DIR string `help:"dir to make"` 243 } 244 shellutils.R(&BucketMakrdirOptions{}, "bucket-mkdir", "Mkdir in a bucket", func(cli cloudprovider.ICloudRegion, args *BucketMakrdirOptions) error { 245 bucket, err := cli.GetIBucketById(args.BUCKET) 246 if err != nil { 247 return err 248 } 249 err = cloudprovider.Makedir(context.Background(), bucket, args.DIR) 250 if err != nil { 251 return err 252 } 253 fmt.Printf("Mkdir success\n") 254 return nil 255 }) 256 257 type BucketPutObjectOptions struct { 258 BUCKET string `help:"name of bucket to put object"` 259 KEY string `help:"key of object"` 260 Path string `help:"Path of file to upload"` 261 262 BlockSize int64 `help:"blocksz in MB" default:"100"` 263 264 Acl string `help:"acl" choices:"private|public-read|public-read-write"` 265 266 StorageClass string `help:"storage class"` 267 268 ObjectHeaderOptions 269 } 270 shellutils.R(&BucketPutObjectOptions{}, "put-object", "Put object into a bucket", func(cli cloudprovider.ICloudRegion, args *BucketPutObjectOptions) error { 271 bucket, err := cli.GetIBucketById(args.BUCKET) 272 if err != nil { 273 return err 274 } 275 276 originMeta := args.ObjectHeaderOptions.Options2Header() 277 278 if len(args.Path) > 0 { 279 uploadFile := func(key, path string) error { 280 meta := http.Header{} 281 for k, v := range originMeta { 282 meta[k] = v 283 } 284 285 finfo, err := os.Stat(path) 286 if err != nil { 287 return errors.Wrap(err, "os.Stat") 288 } 289 fSize := finfo.Size() 290 file, err := os.Open(path) 291 if err != nil { 292 return errors.Wrap(err, "os.Open") 293 } 294 defer file.Close() 295 296 if contTypes, ok := meta[cloudprovider.META_HEADER_CONTENT_TYPE]; !ok || len(contTypes) == 0 { 297 var ext string 298 lastSlashPos := strings.LastIndex(path, "/") 299 lastExtPos := strings.LastIndex(path, ".") 300 if lastExtPos >= 0 && lastExtPos > lastSlashPos { 301 ext = path[lastExtPos:] 302 } 303 if len(ext) > 0 { 304 contType := mime.TypeByExtension(ext) 305 meta.Set(cloudprovider.META_HEADER_CONTENT_TYPE, contType) 306 } 307 } 308 309 err = cloudprovider.UploadObject(context.Background(), bucket, key, args.BlockSize*1000*1000, file, fSize, cloudprovider.TBucketACLType(args.Acl), args.StorageClass, meta, true) 310 if err != nil { 311 return err 312 } 313 314 return nil 315 } 316 if fileutils2.IsFile(args.Path) { 317 err := uploadFile(args.KEY, args.Path) 318 if err != nil { 319 return errors.Wrap(err, "uploadFile") 320 } 321 } else if fileutils2.IsDir(args.Path) { 322 return filepath.Walk(args.Path, func(path string, info os.FileInfo, err error) error { 323 if err != nil { 324 return err 325 } 326 if info.Mode().IsRegular() { 327 rel, _ := filepath.Rel(args.Path, path) 328 src := path 329 dst := filepath.Join(args.KEY, rel) 330 fmt.Println("upload", src, "to", dst) 331 uploadErr := uploadFile(dst, src) 332 if uploadErr != nil { 333 return uploadErr 334 } 335 } 336 return nil 337 }) 338 } 339 } else { 340 err = cloudprovider.UploadObject(context.Background(), bucket, args.KEY, args.BlockSize*1000*1000, os.Stdin, 0, cloudprovider.TBucketACLType(args.Acl), args.StorageClass, originMeta, true) 341 if err != nil { 342 return err 343 } 344 } 345 346 fmt.Printf("Upload success\n") 347 return nil 348 }) 349 350 type BucketDeleteObjectOptions struct { 351 BUCKET string `help:"name of bucket to put object"` 352 KEY string `help:"key of object"` 353 } 354 shellutils.R(&BucketDeleteObjectOptions{}, "delete-object", "Delete object from a bucket", func(cli cloudprovider.ICloudRegion, args *BucketDeleteObjectOptions) error { 355 bucket, err := cli.GetIBucketById(args.BUCKET) 356 if err != nil { 357 return err 358 } 359 err = bucket.DeleteObject(context.Background(), args.KEY) 360 if err != nil { 361 return err 362 } 363 fmt.Printf("Delete success\n") 364 return nil 365 }) 366 367 shellutils.R(&BucketDeleteObjectOptions{}, "delete-prefix", "Delete object from a bucket", func(cli cloudprovider.ICloudRegion, args *BucketDeleteObjectOptions) error { 368 bucket, err := cli.GetIBucketById(args.BUCKET) 369 if err != nil { 370 return err 371 } 372 err = cloudprovider.DeletePrefix(context.Background(), bucket, args.KEY) 373 if err != nil { 374 return err 375 } 376 fmt.Printf("Delete success\n") 377 return nil 378 }) 379 380 type BucketTempUrlOption struct { 381 BUCKET string `help:"name of bucket to put object"` 382 METHOD string `help:"http method" choices:"GET|PUT|DELETE"` 383 KEY string `help:"key of object"` 384 Duration int `help:"duration in seconds" default:"60"` 385 } 386 shellutils.R(&BucketTempUrlOption{}, "temp-url", "generate temp url", func(cli cloudprovider.ICloudRegion, args *BucketTempUrlOption) error { 387 bucket, err := cli.GetIBucketById(args.BUCKET) 388 if err != nil { 389 return err 390 } 391 urlStr, err := bucket.GetTempUrl(args.METHOD, args.KEY, time.Duration(args.Duration)*time.Second) 392 if err != nil { 393 return err 394 } 395 fmt.Println(urlStr) 396 return nil 397 }) 398 399 type BucketAclOption struct { 400 BUCKET string `help:"name of bucket to put object"` 401 KEY string `help:"key of object"` 402 } 403 shellutils.R(&BucketAclOption{}, "object-acl", "Get object acl", func(cli cloudprovider.ICloudRegion, args *BucketAclOption) error { 404 bucket, err := cli.GetIBucketById(args.BUCKET) 405 if err != nil { 406 return err 407 } 408 object, err := cloudprovider.GetIObject(bucket, args.KEY) 409 if err != nil { 410 return err 411 } 412 fmt.Println(object.GetAcl()) 413 return nil 414 }) 415 416 type BucketSetAclOption struct { 417 BUCKET string `help:"name of bucket to put object"` 418 KEY string `help:"key of object"` 419 ACL string `help:"Target acl" choices:"default|private|public-read|public-read-write"` 420 } 421 shellutils.R(&BucketSetAclOption{}, "object-set-acl", "Get object acl", func(cli cloudprovider.ICloudRegion, args *BucketSetAclOption) error { 422 bucket, err := cli.GetIBucketById(args.BUCKET) 423 if err != nil { 424 return err 425 } 426 object, err := cloudprovider.GetIObject(bucket, args.KEY) 427 if err != nil { 428 return err 429 } 430 err = object.SetAcl(cloudprovider.TBucketACLType(args.ACL)) 431 if err != nil { 432 return err 433 } 434 fmt.Println("Success!") 435 return nil 436 }) 437 438 type BucketSetWebsiteOption struct { 439 BUCKET string `help:"name of bucket to put object"` 440 // 主页 441 Index string `help:"main page"` 442 // 错误时返回的文档 443 ErrorDocument string `help:"error return"` 444 // http或https 445 Protocol string `help:"force https" choices:"http|https"` 446 } 447 shellutils.R(&BucketSetWebsiteOption{}, "bucket-set-website", "Set bucket website", func(cli cloudprovider.ICloudRegion, args *BucketSetWebsiteOption) error { 448 bucket, err := cli.GetIBucketById(args.BUCKET) 449 if err != nil { 450 return err 451 } 452 conf := cloudprovider.SBucketWebsiteConf{ 453 Index: args.Index, 454 ErrorDocument: args.ErrorDocument, 455 Protocol: args.Protocol, 456 } 457 err = bucket.SetWebsite(conf) 458 if err != nil { 459 return err 460 } 461 fmt.Println("Success!") 462 return nil 463 }) 464 465 type BucketGetWebsiteConfOption struct { 466 BUCKET string `help:"name of bucket to put object"` 467 } 468 shellutils.R(&BucketGetWebsiteConfOption{}, "bucket-get-website", "Get bucket website", func(cli cloudprovider.ICloudRegion, args *BucketGetWebsiteConfOption) error { 469 bucket, err := cli.GetIBucketById(args.BUCKET) 470 if err != nil { 471 return err 472 } 473 conf, err := bucket.GetWebsiteConf() 474 if err != nil { 475 return err 476 } 477 printObject(conf) 478 return nil 479 }) 480 481 type BucketDeleteWebsiteConfOption struct { 482 BUCKET string `help:"name of bucket to put object"` 483 } 484 shellutils.R(&BucketDeleteWebsiteConfOption{}, "bucket-delete-website", "Delete bucket website", func(cli cloudprovider.ICloudRegion, args *BucketDeleteWebsiteConfOption) error { 485 bucket, err := cli.GetIBucketById(args.BUCKET) 486 if err != nil { 487 return err 488 } 489 err = bucket.DeleteWebSiteConf() 490 if err != nil { 491 return err 492 } 493 fmt.Println("Success!") 494 return nil 495 }) 496 497 type BucketSetCorsOption struct { 498 BUCKET string `help:"name of bucket to put object"` 499 AllowedMethods []string 500 // 允许的源站,可以设为* 501 AllowedOrigins []string 502 AllowedHeaders []string 503 MaxAgeSeconds int 504 ExposeHeaders []string 505 Id string 506 } 507 shellutils.R(&BucketSetCorsOption{}, "bucket-set-cors", "Set bucket cors", func(cli cloudprovider.ICloudRegion, args *BucketSetCorsOption) error { 508 bucket, err := cli.GetIBucketById(args.BUCKET) 509 if err != nil { 510 return err 511 } 512 rule := cloudprovider.SBucketCORSRule{ 513 AllowedOrigins: args.AllowedOrigins, 514 AllowedMethods: args.AllowedMethods, 515 AllowedHeaders: args.AllowedHeaders, 516 MaxAgeSeconds: args.MaxAgeSeconds, 517 ExposeHeaders: args.ExposeHeaders, 518 Id: args.Id, 519 } 520 err = cloudprovider.SetBucketCORS(bucket, []cloudprovider.SBucketCORSRule{rule}) 521 if err != nil { 522 return err 523 } 524 fmt.Println("Success!") 525 return nil 526 }) 527 528 type BucketGetCorsOption struct { 529 BUCKET string `help:"name of bucket to put object"` 530 } 531 shellutils.R(&BucketGetCorsOption{}, "bucket-get-cors", "Get bucket cors", func(cli cloudprovider.ICloudRegion, args *BucketGetCorsOption) error { 532 bucket, err := cli.GetIBucketById(args.BUCKET) 533 if err != nil { 534 return err 535 } 536 rules, err := bucket.GetCORSRules() 537 if err != nil { 538 return err 539 } 540 printList(rules, len(rules), 0, len(rules), nil) 541 return nil 542 }) 543 544 type BucketDeleteCorsOption struct { 545 BUCKET string `help:"name of bucket to put object"` 546 Ids []string `help:"rule ids to delete"` 547 } 548 shellutils.R(&BucketDeleteCorsOption{}, "bucket-delete-cors", "Delete bucket cors", func(cli cloudprovider.ICloudRegion, args *BucketDeleteCorsOption) error { 549 bucket, err := cli.GetIBucketById(args.BUCKET) 550 if err != nil { 551 return err 552 } 553 result, err := cloudprovider.DeleteBucketCORS(bucket, args.Ids) 554 if err != nil { 555 return err 556 } 557 printList(result, len(result), 0, len(result), nil) 558 fmt.Println("Success!") 559 return nil 560 }) 561 562 type BucketSetRefererOption struct { 563 BUCKET string `help:"name of bucket to put object"` 564 RefererType string `help:"referer type" choices:"Black-List|White-List" default:"Black-List"` 565 DomainList []string 566 // 是否允许空refer 访问 567 AllowEmptyRefer bool `help:"all empty refer access"` 568 Disable bool 569 } 570 shellutils.R(&BucketSetRefererOption{}, "bucket-set-referer", "Set bucket referer", func(cli cloudprovider.ICloudRegion, args *BucketSetRefererOption) error { 571 bucket, err := cli.GetIBucketById(args.BUCKET) 572 if err != nil { 573 return err 574 } 575 conf := cloudprovider.SBucketRefererConf{ 576 DomainList: args.DomainList, 577 RefererType: args.RefererType, 578 AllowEmptyRefer: args.AllowEmptyRefer, 579 Enabled: true, 580 } 581 if args.Disable { 582 conf.Enabled = false 583 } 584 err = bucket.SetReferer(conf) 585 if err != nil { 586 return err 587 } 588 fmt.Println("Success!") 589 return nil 590 591 }) 592 593 type BucketGetPolicyOption struct { 594 BUCKET string `help:"name of bucket to put object"` 595 } 596 shellutils.R(&BucketGetPolicyOption{}, "bucket-get-policy", "get bucket policy", func(cli cloudprovider.ICloudRegion, args *BucketGetPolicyOption) error { 597 bucket, err := cli.GetIBucketById(args.BUCKET) 598 if err != nil { 599 return err 600 } 601 policy, err := bucket.GetPolicy() 602 if err != nil { 603 return err 604 } 605 printList(policy, len(policy), 0, len(policy), nil) 606 return nil 607 }) 608 609 type BucketSetPolicyOption struct { 610 BUCKET string `help:"name of bucket to put object"` 611 // 格式主账号id:子账号id 612 PrincipalId []string 613 // Read|ReadWrite|FullControl 614 CannedAction string 615 // Allow|Deny 616 Effect string 617 // 被授权的资源地址 618 ResourcePath []string 619 // ip 条件 620 IpEquals []string 621 IpNotEquals []string 622 } 623 shellutils.R(&BucketSetPolicyOption{}, "bucket-set-policy", "set bucket policy", func(cli cloudprovider.ICloudRegion, args *BucketSetPolicyOption) error { 624 bucket, err := cli.GetIBucketById(args.BUCKET) 625 if err != nil { 626 return err 627 } 628 opts := cloudprovider.SBucketPolicyStatementInput{} 629 opts.CannedAction = args.CannedAction 630 opts.Effect = args.Effect 631 opts.IpEquals = args.IpEquals 632 opts.IpNotEquals = args.IpNotEquals 633 opts.ResourcePath = args.ResourcePath 634 opts.PrincipalId = args.PrincipalId 635 636 err = bucket.SetPolicy(opts) 637 if err != nil { 638 return err 639 } 640 return nil 641 }) 642 643 type BucketDeletePolicyOption struct { 644 BUCKET string `help:"name of bucket to put object"` 645 Id []string 646 } 647 shellutils.R(&BucketDeletePolicyOption{}, "bucket-delete-policy", "delete bucket policy", func(cli cloudprovider.ICloudRegion, args *BucketDeletePolicyOption) error { 648 bucket, err := cli.GetIBucketById(args.BUCKET) 649 if err != nil { 650 return err 651 } 652 result, err := bucket.DeletePolicy(args.Id) 653 if err != nil { 654 return err 655 } 656 printList(result, len(result), 0, len(result), nil) 657 return nil 658 }) 659 660 type BucketGetRefererOption struct { 661 BUCKET string `help:"name of bucket to put object"` 662 } 663 shellutils.R(&BucketGetRefererOption{}, "bucket-get-referer", "get bucket referer", func(cli cloudprovider.ICloudRegion, args *BucketGetRefererOption) error { 664 bucket, err := cli.GetIBucketById(args.BUCKET) 665 if err != nil { 666 return err 667 } 668 conf, err := bucket.GetReferer() 669 if err != nil { 670 return err 671 } 672 printObject(conf) 673 return nil 674 }) 675 676 type BucketGetCdnDomainOption struct { 677 BUCKET string `help:"name of bucket to put object"` 678 } 679 shellutils.R(&BucketGetCdnDomainOption{}, "bucket-get-cdn-domains", "get bucket cdn domains", func(cli cloudprovider.ICloudRegion, args *BucketGetCdnDomainOption) error { 680 bucket, err := cli.GetIBucketById(args.BUCKET) 681 if err != nil { 682 return err 683 } 684 domains, err := bucket.GetCdnDomains() 685 if err != nil { 686 return err 687 } 688 printList(domains, len(domains), 0, len(domains), nil) 689 return nil 690 }) 691 692 type BucketGetMetadata struct { 693 BUCKET string `help:"name of bucket to put object"` 694 } 695 shellutils.R(&BucketGetMetadata{}, "bucket-tag-list", "List bucket tag", func(cli cloudprovider.ICloudRegion, args *BucketGetMetadata) error { 696 bucket, err := cli.GetIBucketById(args.BUCKET) 697 if err != nil { 698 return err 699 } 700 meta, err := bucket.GetTags() 701 if err != nil { 702 return err 703 } 704 printObject(meta) 705 return nil 706 }) 707 708 type BucketSetMetadate struct { 709 BUCKET string `help:"name of bucket to put object"` 710 Tags []string `help:"Tags info, eg: hypervisor=aliyun、os_type=Linux、os_version"` 711 Replace bool 712 } 713 shellutils.R(&BucketSetMetadate{}, "bucket-set-tag", "set bucket tag", func(cli cloudprovider.ICloudRegion, args *BucketSetMetadate) error { 714 bucket, err := cli.GetIBucketById(args.BUCKET) 715 if err != nil { 716 return err 717 } 718 tags := map[string]string{} 719 for _, tag := range args.Tags { 720 pair := strings.Split(tag, "=") 721 if len(pair) == 2 { 722 tags[pair[0]] = pair[1] 723 } 724 } 725 _, err = cloudprovider.SetBucketTags(context.Background(), bucket, "", tags) 726 if err != nil { 727 return err 728 } 729 fmt.Println("Success!") 730 return nil 731 }) 732 733 type BucketGetUploads struct { 734 BUCKET string `help:"name of bucket to put object"` 735 } 736 shellutils.R(&BucketGetUploads{}, "bucket-get-uploads", "get bucket uploads", func(cli cloudprovider.ICloudRegion, args *BucketGetUploads) error { 737 bucket, err := cli.GetIBucketById(args.BUCKET) 738 if err != nil { 739 return err 740 } 741 uplaods, err := bucket.ListMultipartUploads() 742 printList(uplaods, len(uplaods), 0, len(uplaods), nil) 743 return nil 744 }) 745 746 type BucketObjectDownloadOptions struct { 747 BUCKET string `help:"name of bucket"` 748 KEY string `help:"Key of object"` 749 Output string `help:"target output, default to stdout"` 750 Start int64 `help:"partial download start"` 751 End int64 `help:"partial download end"` 752 } 753 shellutils.R(&BucketObjectDownloadOptions{}, "object-download", "Download", func(cli cloudprovider.ICloudRegion, args *BucketObjectDownloadOptions) error { 754 bucket, err := cli.GetIBucketById(args.BUCKET) 755 if err != nil { 756 return err 757 } 758 obj, err := cloudprovider.GetIObject(bucket, args.KEY) 759 if err != nil { 760 return err 761 } 762 763 var rangeOpt *cloudprovider.SGetObjectRange 764 if args.Start != 0 || args.End != 0 { 765 if args.End <= 0 { 766 args.End = obj.GetSizeBytes() - 1 767 } 768 rangeOpt = &cloudprovider.SGetObjectRange{Start: args.Start, End: args.End} 769 } 770 output, err := bucket.GetObject(context.Background(), args.KEY, rangeOpt) 771 if err != nil { 772 return err 773 } 774 defer output.Close() 775 var target io.Writer 776 if len(args.Output) == 0 { 777 target = os.Stdout 778 } else { 779 fp, err := os.Create(args.Output) 780 if err != nil { 781 return err 782 } 783 defer fp.Close() 784 target = fp 785 } 786 prop, err := streamutils.StreamPipe(output, target, false, nil) 787 if err != nil { 788 return err 789 } 790 if len(args.Output) > 0 { 791 fmt.Println("Success:", prop.Size, "written") 792 } 793 return nil 794 }) 795 796 type BucketObjectTempUrlOptions struct { 797 BUCKET string `help:"name of bucket"` 798 KEY string `help:"Key of object"` 799 Method string `default:"GET" choices:"GET|PUT|POST"` 800 Hour int64 `default:"1"` 801 } 802 803 shellutils.R(&BucketObjectTempUrlOptions{}, "object-temp-url", "Show object temp url", func(cli cloudprovider.ICloudRegion, args *BucketObjectTempUrlOptions) error { 804 bucket, err := cli.GetIBucketById(args.BUCKET) 805 if err != nil { 806 return err 807 } 808 url, err := bucket.GetTempUrl(args.Method, args.KEY, time.Duration(args.Hour)*time.Hour) 809 if err != nil { 810 return err 811 } 812 fmt.Println(url) 813 return nil 814 }) 815 816 type BucketObjectCopyOptions struct { 817 SRC string `help:"name of source bucket"` 818 SRCKEY string `help:"Key of source object"` 819 DST string `help:"name of destination bucket"` 820 DSTKEY string `help:"key of destination object"` 821 Debug bool `help:"show debug info"` 822 BlockSize int64 `help:"block size in MB"` 823 Native bool `help:"Use native copy"` 824 825 ObjectHeaderOptions 826 } 827 shellutils.R(&BucketObjectCopyOptions{}, "object-copy", "Copy object", func(cli cloudprovider.ICloudRegion, args *BucketObjectCopyOptions) error { 828 ctx := context.Background() 829 dstBucket, err := cli.GetIBucketByName(args.DST) 830 if err != nil { 831 return err 832 } 833 srcBucket, err := cli.GetIBucketByName(args.SRC) 834 if err != nil { 835 return err 836 } 837 srcObj, err := cloudprovider.GetIObject(srcBucket, args.SRCKEY) 838 if err != nil { 839 return err 840 } 841 meta := args.ObjectHeaderOptions.Options2Header() 842 if args.Native { 843 err = dstBucket.CopyObject(ctx, args.DSTKEY, args.SRC, args.SRCKEY, srcObj.GetAcl(), srcObj.GetStorageClass(), meta) 844 if err != nil { 845 return err 846 } 847 } else { 848 err = cloudprovider.CopyObject(ctx, args.BlockSize*1000*1000, dstBucket, args.DSTKEY, srcBucket, args.SRCKEY, meta, args.Debug) 849 if err != nil { 850 return err 851 } 852 } 853 fmt.Println("Success!") 854 return nil 855 }) 856 857 type ObjectMetaOptions struct { 858 BUCKET string `help:"bucket name"` 859 KEY string `help:"object key"` 860 } 861 shellutils.R(&ObjectMetaOptions{}, "object-meta", "Show object meta header", func(cli cloudprovider.ICloudRegion, args *ObjectMetaOptions) error { 862 bucket, err := cli.GetIBucketByName(args.BUCKET) 863 if err != nil { 864 return err 865 } 866 obj, err := cloudprovider.GetIObject(bucket, args.KEY) 867 if err != nil { 868 return err 869 } 870 meta := obj.GetMeta() 871 for k, v := range meta { 872 fmt.Println(k, ": ", v[0]) 873 } 874 return nil 875 }) 876 877 type ObjectSetMetaOptions struct { 878 BUCKET string `help:"bucket name"` 879 KEY string `help:"object key"` 880 881 ObjectHeaderOptions 882 } 883 shellutils.R(&ObjectSetMetaOptions{}, "object-set-meta", "Set object meta header", func(cli cloudprovider.ICloudRegion, args *ObjectSetMetaOptions) error { 884 bucket, err := cli.GetIBucketByName(args.BUCKET) 885 if err != nil { 886 return err 887 } 888 obj, err := cloudprovider.GetIObject(bucket, args.KEY) 889 if err != nil { 890 return err 891 } 892 meta := args.ObjectHeaderOptions.Options2Header() 893 err = obj.SetMeta(context.Background(), meta) 894 if err != nil { 895 return err 896 } 897 return nil 898 }) 899 }