From a186abb7ce3a5731928161b97be21d73de583396 Mon Sep 17 00:00:00 2001 From: "yaoyao.xyy" Date: Mon, 12 Dec 2016 14:11:17 +0800 Subject: [PATCH] Add ali cloud VPC network support Signed-off-by: yaoyao.xyy --- Documentation/alicloud-vpc-backend.md | 67 +++ Documentation/img/ali-create-instance.png | Bin 0 -> 90958 bytes Documentation/img/ali-create-key.png | Bin 0 -> 88190 bytes Documentation/img/ali-create-switch.png | Bin 0 -> 55896 bytes Documentation/img/ali-create-vpc.png | Bin 0 -> 37427 bytes Documentation/img/ali-vpc-confirm.png | Bin 0 -> 95176 bytes Documentation/kube-flannel-aliyun.yml | 86 +++ README.md | 9 + backend/alivpc/alivpc.go | 198 +++++++ main.go | 1 + .../denverdino/aliyungo/LICENSE.txt | 191 +++++++ .../github.com/denverdino/aliyungo/README.md | 143 +++++ .../denverdino/aliyungo/common/client.go | 145 ++++++ .../denverdino/aliyungo/common/regions.go | 29 ++ .../denverdino/aliyungo/common/request.go | 101 ++++ .../denverdino/aliyungo/common/types.go | 15 + .../denverdino/aliyungo/common/version.go | 3 + .../denverdino/aliyungo/ecs/client.go | 37 ++ .../denverdino/aliyungo/ecs/client_test.go | 75 +++ .../denverdino/aliyungo/ecs/config_test.go | 34 ++ .../denverdino/aliyungo/ecs/disks.go | 330 ++++++++++++ .../denverdino/aliyungo/ecs/disks_test.go | 151 ++++++ .../denverdino/aliyungo/ecs/images.go | 267 ++++++++++ .../denverdino/aliyungo/ecs/images_test.go | 114 ++++ .../denverdino/aliyungo/ecs/instance_types.go | 37 ++ .../aliyungo/ecs/instance_types_test.go | 17 + .../denverdino/aliyungo/ecs/instances.go | 492 ++++++++++++++++++ .../denverdino/aliyungo/ecs/instances_test.go | 252 +++++++++ .../denverdino/aliyungo/ecs/monitoring.go | 136 +++++ .../aliyungo/ecs/monitoring_test.go | 71 +++ .../denverdino/aliyungo/ecs/networks.go | 249 +++++++++ .../denverdino/aliyungo/ecs/networks_test.go | 66 +++ .../denverdino/aliyungo/ecs/regions.go | 34 ++ .../denverdino/aliyungo/ecs/route_tables.go | 162 ++++++ .../aliyungo/ecs/route_tables_test.go | 51 ++ .../aliyungo/ecs/security_groups.go | 208 ++++++++ .../aliyungo/ecs/security_groups_test.go | 108 ++++ .../denverdino/aliyungo/ecs/snapshots.go | 131 +++++ .../denverdino/aliyungo/ecs/snapshots_test.go | 76 +++ .../denverdino/aliyungo/ecs/tags.go | 120 +++++ .../denverdino/aliyungo/ecs/tags_test.go | 98 ++++ .../denverdino/aliyungo/ecs/vpcs.go | 151 ++++++ .../denverdino/aliyungo/ecs/vpcs_test.go | 177 +++++++ .../denverdino/aliyungo/ecs/vrouters.go | 68 +++ .../denverdino/aliyungo/ecs/vrouters_test.go | 40 ++ .../denverdino/aliyungo/ecs/vswitches.go | 152 ++++++ .../denverdino/aliyungo/ecs/vswitches_test.go | 63 +++ .../denverdino/aliyungo/ecs/zones.go | 60 +++ .../denverdino/aliyungo/metadata/client.go | 344 ++++++++++++ .../aliyungo/metadata/client_test.go | 307 +++++++++++ .../denverdino/aliyungo/util/attempt.go | 76 +++ .../denverdino/aliyungo/util/attempt_test.go | 90 ++++ .../denverdino/aliyungo/util/encoding.go | 152 ++++++ .../denverdino/aliyungo/util/encoding_test.go | 81 +++ .../denverdino/aliyungo/util/iso6801.go | 80 +++ .../denverdino/aliyungo/util/iso6801_test.go | 91 ++++ .../denverdino/aliyungo/util/signature.go | 40 ++ .../aliyungo/util/signature_test.go | 14 + .../denverdino/aliyungo/util/util.go | 147 ++++++ .../denverdino/aliyungo/util/util_test.go | 50 ++ 60 files changed, 6487 insertions(+) create mode 100644 Documentation/alicloud-vpc-backend.md create mode 100644 Documentation/img/ali-create-instance.png create mode 100644 Documentation/img/ali-create-key.png create mode 100644 Documentation/img/ali-create-switch.png create mode 100644 Documentation/img/ali-create-vpc.png create mode 100644 Documentation/img/ali-vpc-confirm.png create mode 100644 Documentation/kube-flannel-aliyun.yml create mode 100644 backend/alivpc/alivpc.go create mode 100644 vendor/github.com/denverdino/aliyungo/LICENSE.txt create mode 100644 vendor/github.com/denverdino/aliyungo/README.md create mode 100644 vendor/github.com/denverdino/aliyungo/common/client.go create mode 100644 vendor/github.com/denverdino/aliyungo/common/regions.go create mode 100644 vendor/github.com/denverdino/aliyungo/common/request.go create mode 100644 vendor/github.com/denverdino/aliyungo/common/types.go create mode 100644 vendor/github.com/denverdino/aliyungo/common/version.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/client.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/client_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/config_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/disks.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/disks_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/images.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/images_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/instance_types.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/instance_types_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/instances.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/instances_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/monitoring.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/monitoring_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/networks.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/networks_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/regions.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/route_tables.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/route_tables_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/security_groups.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/security_groups_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/snapshots.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/snapshots_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/tags.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/tags_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/vpcs.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/vpcs_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/vrouters.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/vrouters_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/vswitches.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/vswitches_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/ecs/zones.go create mode 100644 vendor/github.com/denverdino/aliyungo/metadata/client.go create mode 100644 vendor/github.com/denverdino/aliyungo/metadata/client_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/attempt.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/attempt_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/encoding.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/encoding_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/iso6801.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/iso6801_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/signature.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/signature_test.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/util.go create mode 100644 vendor/github.com/denverdino/aliyungo/util/util_test.go diff --git a/Documentation/alicloud-vpc-backend.md b/Documentation/alicloud-vpc-backend.md new file mode 100644 index 0000000000..328198e08d --- /dev/null +++ b/Documentation/alicloud-vpc-backend.md @@ -0,0 +1,67 @@ +# AliCloud VPC Backend for Flannel + +When running in an AliCloud VPC, we recommend using the ali-vpc backend to build your network. This prevent from package encapsulation compare to overlay network and achieve maximum performance with IP routes. Also, there is no need for an separate flannel interface to be created. +In order to run flannel on AliCloud we need first create an [AliCloud VPC Network](https://vpc.console.aliyun.com/#/vpc/cn-hangzhou/list) + +### Create VPC network +Navigate to AliCloud VPC Network list page, then click [create vpc network] button. +![vpc](img/ali-create-vpc.png) + +- Set vpc name with some meaningful string. +- Choose a subnet for the VPC. There are three subnet for you to select which is 192.168.0.0/16 172.16.0.0/12 10.0.0.0/8. Choose one according to your cluster size. +- Click create and wait for ready. + +### Create switch +Click manager switch to navigate to switch list page, and create a switch. + +- Set switch name to a meaningful string. +- Choose one AV Zone where you want to run your ECS +- Set up a subnet which should be contained in your VPC subnet. Here we set subnet as 192.168.0.0/16. +- Confirm Creating. + +### Create instance +Create an instance whose network type is VPC and then add the instance to your previous VPC network. Note: The ECS you created must sit in the same AV zone with your previous created switch. +![create instance](img/ali-create-instance.png) + +- Select the proper VPC network. + +### Get your own ACCESS_KEY_ID and ACCESS_KEY_SECRET. +Click [find key](https://ak-console.aliyun.com/#/accesskey) + +![create key](img/ali-create-key.png) + +- If you havent create any key yet, just click [create key secret] to create a new one. +- take a note of AccessKeyId and AccessKeySecret for further use. + +### Go ahead and launch the instance! + +All that’s left now is to start etcd, publish the network configuration and run the flannel daemon. +First, SSH into `instance-1`: + +- Start etcd: + +``` +$ etcd2 -advertise-client-urls http://$INTERNAL_IP:2379 -listen-client-urls http://0.0.0.0:2379 +``` +- Publish configuration in etcd (ensure that the network range does not overlap with the one configured for the VPC) + +``` +$ etcdctl set /coreos.com/network/config '{"Network":"10.24.0.0/16", "Backend": {"Type": "ali-vpc"}}' +``` +- Fetch the latest release using wget from https://github.com/coreos/flannel/ +- make dist/flanneld +- Run flannel daemon: + +``` +sudo ./flanneld --etcd-endpoints=http://127.0.0.1:2379 +``` + +Next, create and connect to a clone of `instance-1`. +Run flannel with the `--etcd-endpoints` flag set to the *internal* IP of the instance running etcd. + +Confirm that the subnet route table has entries for the lease acquired by each of the subnets. + +![router-confirm](img/ali-vpc-confirm.png) +### Limitations + +Keep in mind that the AliCloud VPC [limits](https://vpc.console.aliyun.com/#/vpc/cn-hangzhou/detail/vpc-bp11xpfe5ev6wvhfb14b6/router) the number of entries per route table to 50. If you require more routes, request a quota increase or simply switch to the VXLAN backend. diff --git a/Documentation/img/ali-create-instance.png b/Documentation/img/ali-create-instance.png new file mode 100644 index 0000000000000000000000000000000000000000..5184eabe9e63933abe1fc036c7f342fec5fd3f4d GIT binary patch literal 90958 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 z z!@LS(x=X2Ob62GSWNnzXW9({)M9my54{V5_DKjqZw1vT|P@Y8RtD8V%M=pn2Ug;RN z1oaUt^X&~4{$Dp!<%Yd?C>2n)5+fmJE!+R2xO4qV`T*m&6Q`KB$x6d}h;qz|v*bEBaKEzvY0TYmQS~t$;=_`PnU9zK@>e6_*T6%|&Sb4J z-!u|%qpxe^>K>f!El2Um!AjL#VQBZ%XkDI6>eN?kETsBJ^`7WpfHGJ{L6}*rttr<2 z?zvaG7vf!m4)-rC`gsOjXdtuYP{Vqvr4Pa{qCB~|$X#7+XWj30xyOC72c|}js(+Y` zQ&f$AIIchteJ`>sQ|_F$H1kUWf%mt(=A|M0fowLP284?yWLBLMyOolU4DKgNpaMb> z8r39?wfxD+Gq-3NVxMa*i7a1Sa?AVgu*#A=srjr4qCTNDW!{1Dz$f4My*&|**RuB-Is z0whyMRgeHxEeK_fqkQiM746}M{COqsnKGXegc&N8I3Rb=-*kk02P};aIx0g&U=OVg z!BLf9X(bTIWNLRkhbjlJ%Mfe>O8!kYp-RVqy32(h3`K3pC85BcU{|j!oU_V6l&qZ0 z#v<>yRnp?xFkQqG24QB)Inm2a9G3*AKya9;c)+H*k>SPSj^t=M_EP4IwyEuLyc)V- z0NH?Vluk+EKjM>q9)#1VM^Hz)ru=*ufp!yCYk$|F!eM*i)|bV}PXJMa@Ep=ZYt?ppYO0Dbvs;5n9{|GmyOA1g z1+gwf`kKauW`#uRxZqy2tkrnIqAu9mdz>=I*{Q!4~>JXBJDTNDa-9`}dFNoMq|>CN;xGA}8U$FESW*L+1tA#5wR-?ZZ>P z^Dsy0kOeAWedDR#q>UY*n=2=otqm~kALJh%L#w2e{M^#>)GDP$@vvjOOwV;8BsEDz zOpwn5$2RY6FiY0v2#}MJ)6#u>7sey=n^-5rS2=kKeXT)Dy%luOEuW^7PqY(IM)8Yl3YQb z9Sm(D#mo+o!e05`=Tf_t3ADYB;55Ue^9%=PZVTK>EBS*Oz1Ay$IcEVrFv&hmPQCG& zXG8Y@o$r_FTCuBFx6|~_Vo;LiromfU>)RMVu9u@c8cTCNP*ci~fv+k$cA(!{;*D4O z*9&-_&I`>}Y8!yrEEh=kj1Wd4#AcgyM1Xe0*6EUurF30_hw1Em6lmD_39(XVIh`BM z!tGakXNY9x&ptjl8rIg+)&H?^F^y$QQK=mAdGSuPbO-T+Nx zYw>0i1^DGhqhXT=fm0dW9MA!Mv#v3s!M!6%I7)niTyb(92!F^Cu=wVTxil2GsgVo0 z&-vwW1Bv^BN$JR}HzZg^7NWMhO_zL~fgI^UsgBJ}hl^y+&lk}GH;t$%o!w5Lt;k8M z$@t@?lD$vB%lwY@0K*sSpr}~sCiY#m=7cm`8b>y_$Z8?uifex-JHFN^ckv1FVCyyU zJCoBqGE2Y0Br-2zAs2BaV-S`VX2k}JVKoiuCTC;uPtn8Qh@5g!&#+W4{{|cN6CD5m literal 0 HcmV?d00001 diff --git a/Documentation/img/ali-create-key.png b/Documentation/img/ali-create-key.png new file mode 100644 index 0000000000000000000000000000000000000000..0a5f83a6385a261391469c5d6b7ba8beb544c34a GIT binary patch literal 88190 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 f334wN>cSvlBTUEo3}=cyHKX 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 qA~!F9UUN|Dg^K 0 { + if err := json.Unmarshal(config.Backend, &cfg); err != nil { + return nil, fmt.Errorf("error decoding VPC backend config: %v", err) + } + } + log.Infof("Unmarshal Configure : %v\n", cfg) + + // 2. Acquire the lease form subnet manager + attrs := subnet.LeaseAttrs{ + PublicIP: ip.FromIP(be.extIface.ExtAddr), + } + + l, err := be.sm.AcquireLease(ctx, network, &attrs) + switch err { + case nil: + + case context.Canceled, context.DeadlineExceeded: + return nil, err + + default: + return nil, fmt.Errorf("failed to acquire lease: %v", err) + } + if cfg.AccessKeyID == "" || cfg.AccessKeySecret == "" { + cfg.AccessKeyID = os.Getenv("ACCESS_KEY_ID") + cfg.AccessKeySecret = os.Getenv("ACCESS_KEY_SECRET") + + if cfg.AccessKeyID == "" || cfg.AccessKeySecret == "" { + return nil, fmt.Errorf("ACCESS_KEY_ID and ACCESS_KEY_SECRET must be provided! ") + } + } + + meta := metadata.NewMetaData(nil) + REGION, err := meta.Region() + if err != nil { + return nil, err + } + instanceid, err := meta.InstanceID() + if err != nil { + return nil, err + } + VpcID, err := meta.VpcID() + if err != nil { + return nil, err + } + + c := ecs.NewClient(cfg.AccessKeyID, cfg.AccessKeySecret) + + vpc, _, err := c.DescribeVpcs(&ecs.DescribeVpcsArgs{ + RegionId: common.Region(REGION), + VpcId: VpcID, + }) + if err != nil || len(vpc) <= 0 { + log.Errorf("Error DescribeVpcs: %s . \n", getErrorString(err)) + return nil, err + } + + vroute, _, err := c.DescribeVRouters(&ecs.DescribeVRoutersArgs{ + VRouterId: vpc[0].VRouterId, + RegionId: common.Region(REGION), + }) + if err != nil || len(vroute) <= 0 { + log.Errorf("Error DescribeVRouters: %s .\n", getErrorString(err)) + return nil, err + } + vRouterId := vroute[0].VRouterId + rTableId := vroute[0].RouteTableIds.RouteTableId[0] + + rtables, _, err := c.DescribeRouteTables(&ecs.DescribeRouteTablesArgs{ + VRouterId: vRouterId, + RouteTableId: rTableId, + }) + if err != nil || len(rtables) <= 0 { + log.Errorf("Error DescribeRouteTables: %s.\n", err.Error()) + return nil, err + } + + route := &ecs.CreateRouteEntryArgs{ + DestinationCidrBlock: l.Subnet.String(), + NextHopType: ecs.NextHopIntance, + NextHopId: instanceid, + ClientToken: "", + RouteTableId: rTableId, + } + if err := be.recreateRoute(c, rtables[0], route); err != nil { + return nil, err + } + + if err := c.WaitForAllRouteEntriesAvailable(vRouterId, rTableId, 60); err != nil { + return nil, err + } + return &backend.SimpleNetwork{ + SubnetLease: l, + ExtIface: be.extIface, + }, nil +} + +func (be *AliVpcBackend) recreateRoute(c *ecs.Client, table ecs.RouteTableSetType, route *ecs.CreateRouteEntryArgs) error { + exist := false + for _, e := range table.RouteEntrys.RouteEntry { + if e.RouteTableId == route.RouteTableId && + e.Type == ecs.RouteTableCustom && + e.InstanceId == route.NextHopId { + + if e.DestinationCidrBlock == route.DestinationCidrBlock && + e.Status == ecs.RouteEntryStatusAvailable { + exist = true + log.Infof("Keep target entry: rtableid=%s, CIDR=%s, NextHop=%s \n", e.RouteTableId, e.DestinationCidrBlock, e.InstanceId) + continue + } + // Fix: here we delete all the route which targeted to us(instance) except the specified route. + // That means only one CIDR was allowed to target to the instance. Think if We need to change this + // to adapt to multi CIDR and deal with unavailable route entry. + if err := c.DeleteRouteEntry(&ecs.DeleteRouteEntryArgs{ + RouteTableId: route.RouteTableId, + DestinationCidrBlock: e.DestinationCidrBlock, + NextHopId: route.NextHopId, + }); err != nil { + return err + } + + log.Infof("Remove old route entry: rtableid=%s, CIDR=%s, NextHop=%s \n", e.RouteTableId, e.DestinationCidrBlock, e.InstanceId) + continue + } + + log.Infof("Keep route entry: rtableid=%s, CIDR=%s, NextHop=%s \n", e.RouteTableId, e.DestinationCidrBlock, e.InstanceId) + } + if !exist { + return c.CreateRouteEntry(route) + } + return nil +} + +func getErrorString(e error) string { + if e == nil { + return "" + } + return e.Error() +} diff --git a/main.go b/main.go index 3725cafddd..79e9771e59 100644 --- a/main.go +++ b/main.go @@ -40,6 +40,7 @@ import ( _ "github.com/coreos/flannel/backend/hostgw" _ "github.com/coreos/flannel/backend/udp" _ "github.com/coreos/flannel/backend/vxlan" + _ "github.com/coreos/flannel/backend/alivpc" ) type CmdLineOpts struct { diff --git a/vendor/github.com/denverdino/aliyungo/LICENSE.txt b/vendor/github.com/denverdino/aliyungo/LICENSE.txt new file mode 100644 index 0000000000..9182971332 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/LICENSE.txt @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Copyright 2015-2015 Li Yi (denverdino@gmail.com). + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/denverdino/aliyungo/README.md b/vendor/github.com/denverdino/aliyungo/README.md new file mode 100644 index 0000000000..fd9da9b18b --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/README.md @@ -0,0 +1,143 @@ +# AliyunGo: Go SDK for Aliyun Services + +This is an unofficial Go SDK for Aliyun Services. You are welcome for contribution. + + +## Package Structure + +* ecs: [Elastic Compute Service](https://help.aliyun.com/document_detail/ecs/open-api/summary.html) +* oss: [Open Storage Service](https://help.aliyun.com/document_detail/oss/api-reference/abstract.html) +* slb: [Server Load Balancer](https://help.aliyun.com/document_detail/slb/api-reference/brief-introduction.html) +* dns: [DNS](https://help.aliyun.com/document_detail/dns/api-reference/summary.html) +* sls: [Logging Service](https://help.aliyun.com/document_detail/sls/api/overview.html) +* ram: [Resource Access Management](https://help.aliyun.com/document_detail/ram/ram-api-reference/intro/intro.html) +* rds: [Relational Database Service](https://help.aliyun.com/document_detail/26226.html) +* cms: [Cloud Monitor Service](https://help.aliyun.com/document_detail/28615.html) +* sts: [Security Token Service](https://help.aliyun.com/document_detail/28756.html) +* dm: [Direct Mail] +(https://help.aliyun.com/document_detail/29414.html) +* common: Common libary of Aliyun Go SDK +* util: Utility helpers + + + +## Quick Start + +```go +package main + +import ( + "fmt" + + "github.com/denverdino/aliyungo/ecs" +) + +const ACCESS_KEY_ID = "" +const ACCESS_KEY_SECRET = "<****>" + +func main() { + client := ecs.NewClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET) + fmt.Print(client.DescribeRegions()) +} + +``` + +## Documentation + + * ECS: [https://godoc.org/github.com/denverdino/aliyungo/ecs](https://godoc.org/github.com/denverdino/aliyungo/ecs) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/ecs?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/ecs) + * OSS: [https://godoc.org/github.com/denverdino/aliyungo/oss](https://godoc.org/github.com/denverdino/aliyungo/oss) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/oss?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/oss) + * SLB: [https://godoc.org/github.com/denverdino/aliyungo/slb](https://godoc.org/github.com/denverdino/aliyungo/slb) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/slb?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/slb) + * DNS: [https://godoc.org/github.com/denverdino/aliyungo/dns](https://godoc.org/github.com/denverdino/aliyungo/dns) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/dns?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/dns) + * SLS: [https://godoc.org/github.com/denverdino/aliyungo/sls](https://godoc.org/github.com/denverdino/aliyungo/sls) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/sls?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/sls) + * RAM: [https://godoc.org/github.com/denverdino/aliyungo/ram](https://godoc.org/github.com/denverdino/aliyungo/ram) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/ram?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/ram) + * RDS: [https://godoc.org/github.com/denverdino/aliyungo/rds](https://godoc.org/github.com/denverdino/aliyungo/rds) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/rds?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/rds) + * CMS: [https://godoc.org/github.com/denverdino/aliyungo/cms](https://godoc.org/github.com/denverdino/aliyungo/cms) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/cms?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/cms) + * STS: [https://godoc.org/github.com/denverdino/aliyungo/sts](https://godoc.org/github.com/denverdino/aliyungo/sts) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/sts?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/sts) + * DM: [https://godoc.org/github.com/denverdino/aliyungo/dm](https://godoc.org/github.com/denverdino/aliyungo/dm) [![GoDoc](https://godoc.org/github.com/denverdino/aliyungo/dm?status.svg)](https://godoc.org/github.com/denverdino/aliyungo/dm) + +## Build and Install + +go get: + +```sh +go get github.com/denverdino/aliyungo +``` + + +## Test ECS + +Modify "ecs/config_test.go" + +```sh + TestAccessKeyId = "MY_ACCESS_KEY_ID" + TestAccessKeySecret = "MY_ACCESS_KEY_ID" + TestInstanceId = "MY_INSTANCE_ID" + TestIAmRich = false +``` + +* TestAccessKeyId: the Access Key Id +* TestAccessKeySecret: the Access Key Secret. +* TestInstanceId: the existing instance id for testing. It will be stopped and restarted during testing. +* TestIAmRich(Optional): If it is set to true, it will perform tests to create virtual machines and disks under your account. And you will pay the bill. :-) + +Under "ecs" and run + +```sh +go test +``` + +## Test OSS + +Modify "oss/config_test.go" + +```sh + TestAccessKeyId = "MY_ACCESS_KEY_ID" + TestAccessKeySecret = "MY_ACCESS_KEY_ID" + TestRegion = oss.Beijing + TestBucket = "denverdino" +``` + +* TestAccessKeyId: the Access Key Id +* TestAccessKeySecret: the Access Key Secret. +* TestRegion: the region of OSS for testing +* TestBucket: the bucket name for testing + + +Under "oss" and run + +```sh +go test +``` + +## Contributors + + * Li Yi (denverdino@gmail.com) + * tgic (farmer1992@gmail.com) + * Yu Zhou (oscarrr110@gmail.com) + * Yufei Zhang + * linuxlikerqq + * Changhai Yan (changhai.ych@alibaba-inc.com) + * Jizhong Jiang (jiangjizhong@gmail.com) + * Kent Wang (pragkent@gmail.com) + * ringtail (zhongwei.lzw@alibaba-inc.com) + * aiden0z (aiden0xz@gmail.com) + * jimmycmh + * menglingwei + * mingang.he (dustgle@gmail.com) + * chainone (chainone@gmail.com) + * johnzeng + +## License +This project is licensed under the Apache License, Version 2.0. See [LICENSE](https://github.com/denverdino/aliyungo/blob/master/LICENSE.txt) for the full license text. + + +## Related projects + + * Aliyun ECS driver for Docker Machine: [Pull request](https://github.com/docker/machine/pull/1182) + + * Aliyun OSS driver for Docker Registry V2: [Pull request](https://github.com/docker/distribution/pull/514) + + +## References + +The GO API design of OSS refer the implementation from [https://github.com/AdRoll/goamz](https://github.com/AdRoll) diff --git a/vendor/github.com/denverdino/aliyungo/common/client.go b/vendor/github.com/denverdino/aliyungo/common/client.go new file mode 100644 index 0000000000..4ed0a06f2d --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/common/client.go @@ -0,0 +1,145 @@ +package common + +import ( + "bytes" + "encoding/json" + "io/ioutil" + "log" + "net/http" + "net/url" + "time" + + "github.com/denverdino/aliyungo/util" +) + +// A Client represents a client of ECS services +type Client struct { + AccessKeyId string //Access Key Id + AccessKeySecret string //Access Key Secret + debug bool + httpClient *http.Client + endpoint string + version string +} + +// NewClient creates a new instance of ECS client +func (client *Client) Init(endpoint, version, accessKeyId, accessKeySecret string) { + client.AccessKeyId = accessKeyId + client.AccessKeySecret = accessKeySecret + "&" + client.debug = false + client.httpClient = &http.Client{} + client.endpoint = endpoint + client.version = version +} + +// SetEndpoint sets custom endpoint +func (client *Client) SetEndpoint(endpoint string) { + client.endpoint = endpoint +} + +// SetEndpoint sets custom version +func (client *Client) SetVersion(version string) { + client.version = version +} + +// SetAccessKeyId sets new AccessKeyId +func (client *Client) SetAccessKeyId(id string) { + client.AccessKeyId = id +} + +// SetAccessKeySecret sets new AccessKeySecret +func (client *Client) SetAccessKeySecret(secret string) { + client.AccessKeySecret = secret + "&" +} + +// SetDebug sets debug mode to log the request/response message +func (client *Client) SetDebug(debug bool) { + client.debug = debug +} + +// Invoke sends the raw HTTP request for ECS services +func (client *Client) Invoke(action string, args interface{}, response interface{}) error { + + request := Request{} + request.init(client.version, action, client.AccessKeyId) + + query := util.ConvertToQueryValues(request) + util.SetQueryValues(args, &query) + + // Sign request + signature := util.CreateSignatureForRequest(ECSRequestMethod, &query, client.AccessKeySecret) + + // Generate the request URL + requestURL := client.endpoint + "?" + query.Encode() + "&Signature=" + url.QueryEscape(signature) + + httpReq, err := http.NewRequest(ECSRequestMethod, requestURL, nil) + + // TODO move to util and add build val flag + httpReq.Header.Set("X-SDK-Client", `AliyunGO/`+Version) + + if err != nil { + return GetClientError(err) + } + + t0 := time.Now() + httpResp, err := client.httpClient.Do(httpReq) + t1 := time.Now() + if err != nil { + return GetClientError(err) + } + statusCode := httpResp.StatusCode + + if client.debug { + log.Printf("Invoke %s %s %d (%v)", ECSRequestMethod, requestURL, statusCode, t1.Sub(t0)) + } + + defer httpResp.Body.Close() + body, err := ioutil.ReadAll(httpResp.Body) + + if err != nil { + return GetClientError(err) + } + + if client.debug { + var prettyJSON bytes.Buffer + err = json.Indent(&prettyJSON, body, "", " ") + log.Println(string(prettyJSON.Bytes())) + } + + if statusCode >= 400 && statusCode <= 599 { + errorResponse := ErrorResponse{} + err = json.Unmarshal(body, &errorResponse) + ecsError := &Error{ + ErrorResponse: errorResponse, + StatusCode: statusCode, + } + return ecsError + } + + err = json.Unmarshal(body, response) + //log.Printf("%++v", response) + if err != nil { + return GetClientError(err) + } + + return nil +} + +// GenerateClientToken generates the Client Token with random string +func (client *Client) GenerateClientToken() string { + return util.CreateRandomString() +} + +func GetClientErrorFromString(str string) error { + return &Error{ + ErrorResponse: ErrorResponse{ + Code: "AliyunGoClientFailure", + Message: str, + }, + StatusCode: -1, + } +} + +func GetClientError(err error) error { + return GetClientErrorFromString(err.Error()) +} diff --git a/vendor/github.com/denverdino/aliyungo/common/regions.go b/vendor/github.com/denverdino/aliyungo/common/regions.go new file mode 100644 index 0000000000..781a727bc1 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/common/regions.go @@ -0,0 +1,29 @@ +package common + +// Region represents ECS region +type Region string + +// Constants of region definition +const ( + Hangzhou = Region("cn-hangzhou") + Qingdao = Region("cn-qingdao") + Beijing = Region("cn-beijing") + Hongkong = Region("cn-hongkong") + Shenzhen = Region("cn-shenzhen") + USWest1 = Region("us-west-1") + USEast1 = Region("us-east-1") + APSouthEast1 = Region("ap-southeast-1") + Shanghai = Region("cn-shanghai") + MEEast1 = Region("me-east-1") + APNorthEast1 = Region("ap-northeast-1") + APSouthEast2 = Region("ap-southeast-2") + EUCentral1 = Region("eu-central-1") +) + +var ValidRegions = []Region{ + Hangzhou, Qingdao, Beijing, Shenzhen, Hongkong, Shanghai, + USWest1, USEast1, + APNorthEast1, APSouthEast1, APSouthEast2, + MEEast1, + EUCentral1, +} diff --git a/vendor/github.com/denverdino/aliyungo/common/request.go b/vendor/github.com/denverdino/aliyungo/common/request.go new file mode 100644 index 0000000000..2a883f19b2 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/common/request.go @@ -0,0 +1,101 @@ +package common + +import ( + "fmt" + "log" + "time" + + "github.com/denverdino/aliyungo/util" +) + +// Constants for Aliyun API requests +const ( + SignatureVersion = "1.0" + SignatureMethod = "HMAC-SHA1" + JSONResponseFormat = "JSON" + XMLResponseFormat = "XML" + ECSRequestMethod = "GET" +) + +type Request struct { + Format string + Version string + AccessKeyId string + Signature string + SignatureMethod string + Timestamp util.ISO6801Time + SignatureVersion string + SignatureNonce string + ResourceOwnerAccount string + Action string +} + +func (request *Request) init(version string, action string, AccessKeyId string) { + request.Format = JSONResponseFormat + request.Timestamp = util.NewISO6801Time(time.Now().UTC()) + request.Version = version + request.SignatureVersion = SignatureVersion + request.SignatureMethod = SignatureMethod + request.SignatureNonce = util.CreateRandomString() + request.Action = action + request.AccessKeyId = AccessKeyId +} + +type Response struct { + RequestId string +} + +type ErrorResponse struct { + Response + HostId string + Code string + Message string +} + +// An Error represents a custom error for Aliyun API failure response +type Error struct { + ErrorResponse + StatusCode int //Status Code of HTTP Response +} + +func (e *Error) Error() string { + return fmt.Sprintf("Aliyun API Error: RequestId: %s Status Code: %d Code: %s Message: %s", e.RequestId, e.StatusCode, e.Code, e.Message) +} + +type Pagination struct { + PageNumber int + PageSize int +} + +func (p *Pagination) SetPageSize(size int) { + p.PageSize = size +} + +func (p *Pagination) Validate() { + if p.PageNumber < 0 { + log.Printf("Invalid PageNumber: %d", p.PageNumber) + p.PageNumber = 1 + } + if p.PageSize < 0 { + log.Printf("Invalid PageSize: %d", p.PageSize) + p.PageSize = 10 + } else if p.PageSize > 50 { + log.Printf("Invalid PageSize: %d", p.PageSize) + p.PageSize = 50 + } +} + +// A PaginationResponse represents a response with pagination information +type PaginationResult struct { + TotalCount int + PageNumber int + PageSize int +} + +// NextPage gets the next page of the result set +func (r *PaginationResult) NextPage() *Pagination { + if r.PageNumber*r.PageSize >= r.TotalCount { + return nil + } + return &Pagination{PageNumber: r.PageNumber + 1, PageSize: r.PageSize} +} diff --git a/vendor/github.com/denverdino/aliyungo/common/types.go b/vendor/github.com/denverdino/aliyungo/common/types.go new file mode 100644 index 0000000000..c562aedfc2 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/common/types.go @@ -0,0 +1,15 @@ +package common + +type InternetChargeType string + +const ( + PayByBandwidth = InternetChargeType("PayByBandwidth") + PayByTraffic = InternetChargeType("PayByTraffic") +) + +type InstanceChargeType string + +const ( + PrePaid = InstanceChargeType("PrePaid") + PostPaid = InstanceChargeType("PostPaid") +) diff --git a/vendor/github.com/denverdino/aliyungo/common/version.go b/vendor/github.com/denverdino/aliyungo/common/version.go new file mode 100644 index 0000000000..7cb3d3aff0 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/common/version.go @@ -0,0 +1,3 @@ +package common + +const Version = "0.1" diff --git a/vendor/github.com/denverdino/aliyungo/ecs/client.go b/vendor/github.com/denverdino/aliyungo/ecs/client.go new file mode 100644 index 0000000000..063c0738c0 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/client.go @@ -0,0 +1,37 @@ +package ecs + +import ( + "github.com/denverdino/aliyungo/common" + "os" +) + +// Interval for checking status in WaitForXXX method +const DefaultWaitForInterval = 5 + +// Default timeout value for WaitForXXX method +const DefaultTimeout = 60 + +type Client struct { + common.Client +} + +const ( + // ECSDefaultEndpoint is the default API endpoint of ECS services + ECSDefaultEndpoint = "https://ecs-cn-hangzhou.aliyuncs.com" + ECSAPIVersion = "2014-05-26" +) + +// NewClient creates a new instance of ECS client +func NewClient(accessKeyId, accessKeySecret string) *Client { + endpoint := os.Getenv("ECS_ENDPOINT") + if endpoint == "" { + endpoint = ECSDefaultEndpoint + } + return NewClientWithEndpoint(endpoint, accessKeyId, accessKeySecret) +} + +func NewClientWithEndpoint(endpoint string, accessKeyId, accessKeySecret string) *Client { + client := &Client{} + client.Init(endpoint, ECSAPIVersion, accessKeyId, accessKeySecret) + return client +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/client_test.go b/vendor/github.com/denverdino/aliyungo/ecs/client_test.go new file mode 100644 index 0000000000..629ee94177 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/client_test.go @@ -0,0 +1,75 @@ +package ecs + +import ( + "testing" +) + +func TestGenerateClientToken(t *testing.T) { + client := NewTestClient() + for i := 0; i < 10; i++ { + t.Log("GenerateClientToken: ", client.GenerateClientToken()) + } + +} + +func TestECSDescribe(t *testing.T) { + if TestQuick { + return + } + client := NewTestClient() + + regions, err := client.DescribeRegions() + + t.Log("regions: ", regions, err) + + for _, region := range regions { + zones, err := client.DescribeZones(region.RegionId) + t.Log("zones: ", zones, err) + for _, zone := range zones { + args := DescribeInstanceStatusArgs{ + RegionId: region.RegionId, + ZoneId: zone.ZoneId, + } + instanceStatuses, pagination, err := client.DescribeInstanceStatus(&args) + t.Logf("instanceStatuses: %v, %++v, %v", instanceStatuses, pagination, err) + for _, instanceStatus := range instanceStatuses { + instance, err := client.DescribeInstanceAttribute(instanceStatus.InstanceId) + t.Logf("Instance: %++v", instance) + t.Logf("Error: %++v", err) + } + args1 := DescribeInstancesArgs{ + RegionId: region.RegionId, + ZoneId: zone.ZoneId, + } + instances, _, err := client.DescribeInstances(&args1) + if err != nil { + t.Errorf("Failed to describe instance by region %s zone %s: %v", region.RegionId, zone.ZoneId, err) + } else { + for _, instance := range instances { + t.Logf("Instance: %++v", instance) + } + } + + } + args := DescribeImagesArgs{RegionId: region.RegionId} + + for { + + images, pagination, err := client.DescribeImages(&args) + if err != nil { + t.Fatalf("Failed to describe images: %v", err) + break + } else { + t.Logf("Image count for region %s total %d from %d", region.RegionId, pagination.TotalCount, pagination.PageNumber*pagination.PageSize) + for _, image := range images { + t.Logf("Image: %++v", image) + } + nextPage := pagination.NextPage() + if nextPage == nil { + break + } + args.Pagination = *nextPage + } + } + } +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/config_test.go b/vendor/github.com/denverdino/aliyungo/ecs/config_test.go new file mode 100644 index 0000000000..2668b509d8 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/config_test.go @@ -0,0 +1,34 @@ +package ecs + +//Modify with your Access Key Id and Access Key Secret + +const ( + TestAccessKeyId = "MY_ACCESS_KEY_ID" + TestAccessKeySecret = "MY_ACCESS_KEY_SECRET" + TestInstanceId = "MY_TEST_INSTANCE_ID" + TestSecurityGroupId = "MY_TEST_SECURITY_GROUP_ID" + TestImageId = "MY_TEST_IMAGE_ID" + TestAccountId = "MY_TEST_ACCOUNT_ID" //Get from https://account.console.aliyun.com + + TestIAmRich = false + TestQuick = false +) + +var testClient *Client + +func NewTestClient() *Client { + if testClient == nil { + testClient = NewClient(TestAccessKeyId, TestAccessKeySecret) + } + return testClient +} + +var testDebugClient *Client + +func NewTestClientForDebug() *Client { + if testDebugClient == nil { + testDebugClient = NewClient(TestAccessKeyId, TestAccessKeySecret) + testDebugClient.SetDebug(true) + } + return testDebugClient +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/disks.go b/vendor/github.com/denverdino/aliyungo/ecs/disks.go new file mode 100644 index 0000000000..f9d4f1c96c --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/disks.go @@ -0,0 +1,330 @@ +package ecs + +import ( + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +// Types of disks +type DiskType string + +const ( + DiskTypeAll = DiskType("all") //Default + DiskTypeAllSystem = DiskType("system") + DiskTypeAllData = DiskType("data") +) + +// Categories of disks +type DiskCategory string + +const ( + DiskCategoryAll = DiskCategory("all") //Default + DiskCategoryCloud = DiskCategory("cloud") + DiskCategoryEphemeral = DiskCategory("ephemeral") + DiskCategoryEphemeralSSD = DiskCategory("ephemeral_ssd") + DiskCategoryCloudEfficiency = DiskCategory("cloud_efficiency") + DiskCategoryCloudSSD = DiskCategory("cloud_ssd") +) + +// Status of disks +type DiskStatus string + +const ( + DiskStatusInUse = DiskStatus("In_use") + DiskStatusAvailable = DiskStatus("Available") + DiskStatusAttaching = DiskStatus("Attaching") + DiskStatusDetaching = DiskStatus("Detaching") + DiskStatusCreating = DiskStatus("Creating") + DiskStatusReIniting = DiskStatus("ReIniting") + DiskStatusAll = DiskStatus("All") //Default +) + +// Charge type of disks +type DiskChargeType string + +const ( + PrePaid = DiskChargeType("PrePaid") + PostPaid = DiskChargeType("PostPaid") +) + +// A DescribeDisksArgs defines the arguments to describe disks +type DescribeDisksArgs struct { + RegionId common.Region + ZoneId string + DiskIds []string + InstanceId string + DiskType DiskType //enum for all(default) | system | data + Category DiskCategory //enum for all(default) | cloud | ephemeral + Status DiskStatus //enum for In_use | Available | Attaching | Detaching | Creating | ReIniting | All(default) + SnapshotId string + Name string + Portable *bool //optional + DeleteWithInstance *bool //optional + DeleteAutoSnapshot *bool //optional + EnableAutoSnapshot *bool //optional + DiskChargeType DiskChargeType + Tag map[string]string + common.Pagination +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&diskitemtype +type DiskItemType struct { + DiskId string + RegionId common.Region + ZoneId string + DiskName string + Description string + Type DiskType + Category DiskCategory + Size int + ImageId string + SourceSnapshotId string + ProductCode string + Portable bool + Status DiskStatus + OperationLocks OperationLocksType + InstanceId string + Device string + DeleteWithInstance bool + DeleteAutoSnapshot bool + EnableAutoSnapshot bool + CreationTime util.ISO6801Time + AttachedTime util.ISO6801Time + DetachedTime util.ISO6801Time + DiskChargeType DiskChargeType +} + +type DescribeDisksResponse struct { + common.Response + common.PaginationResult + RegionId common.Region + Disks struct { + Disk []DiskItemType + } +} + +// DescribeDisks describes Disks +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&describedisks +func (client *Client) DescribeDisks(args *DescribeDisksArgs) (disks []DiskItemType, pagination *common.PaginationResult, err error) { + response := DescribeDisksResponse{} + + err = client.Invoke("DescribeDisks", args, &response) + + if err != nil { + return nil, nil, err + } + + return response.Disks.Disk, &response.PaginationResult, err +} + +type CreateDiskArgs struct { + RegionId common.Region + ZoneId string + DiskName string + Description string + DiskCategory DiskCategory + Size int + SnapshotId string + ClientToken string +} + +type CreateDisksResponse struct { + common.Response + DiskId string +} + +// CreateDisk creates a new disk +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&createdisk +func (client *Client) CreateDisk(args *CreateDiskArgs) (diskId string, err error) { + response := CreateDisksResponse{} + err = client.Invoke("CreateDisk", args, &response) + if err != nil { + return "", err + } + return response.DiskId, err +} + +type DeleteDiskArgs struct { + DiskId string +} + +type DeleteDiskResponse struct { + common.Response +} + +// DeleteDisk deletes disk +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&deletedisk +func (client *Client) DeleteDisk(diskId string) error { + args := DeleteDiskArgs{ + DiskId: diskId, + } + response := DeleteDiskResponse{} + err := client.Invoke("DeleteDisk", &args, &response) + return err +} + +type ReInitDiskArgs struct { + DiskId string +} + +type ReInitDiskResponse struct { + common.Response +} + +// ReInitDisk reinitizes disk +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&reinitdisk +func (client *Client) ReInitDisk(diskId string) error { + args := ReInitDiskArgs{ + DiskId: diskId, + } + response := ReInitDiskResponse{} + err := client.Invoke("ReInitDisk", &args, &response) + return err +} + +type AttachDiskArgs struct { + InstanceId string + DiskId string + Device string + DeleteWithInstance bool +} + +type AttachDiskResponse struct { + common.Response +} + +// AttachDisk attaches disk to instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&attachdisk +func (client *Client) AttachDisk(args *AttachDiskArgs) error { + response := AttachDiskResponse{} + err := client.Invoke("AttachDisk", args, &response) + return err +} + +type DetachDiskArgs struct { + InstanceId string + DiskId string +} + +type DetachDiskResponse struct { + common.Response +} + +// DetachDisk detaches disk from instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&detachdisk +func (client *Client) DetachDisk(instanceId string, diskId string) error { + args := DetachDiskArgs{ + InstanceId: instanceId, + DiskId: diskId, + } + response := DetachDiskResponse{} + err := client.Invoke("DetachDisk", &args, &response) + return err +} + +type ResetDiskArgs struct { + DiskId string + SnapshotId string +} + +type ResetDiskResponse struct { + common.Response +} + +// ResetDisk resets disk to original status +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&resetdisk +func (client *Client) ResetDisk(diskId string, snapshotId string) error { + args := ResetDiskArgs{ + SnapshotId: snapshotId, + DiskId: diskId, + } + response := ResetDiskResponse{} + err := client.Invoke("ResetDisk", &args, &response) + return err +} + +type ModifyDiskAttributeArgs struct { + DiskId string + DiskName string + Description string + DeleteWithInstance *bool + DeleteAutoSnapshot *bool + EnableAutoSnapshot *bool +} + +type ModifyDiskAttributeResponse struct { + common.Response +} + +// ModifyDiskAttribute modifies disk attribute +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/disk&modifydiskattribute +func (client *Client) ModifyDiskAttribute(args *ModifyDiskAttributeArgs) error { + response := ModifyDiskAttributeResponse{} + err := client.Invoke("ModifyDiskAttribute", &args, &response) + return err +} + +type ReplaceSystemDiskArgs struct { + InstanceId string + ImageId string + SystemDisk SystemDiskType + ClientToken string +} + +type ReplaceSystemDiskResponse struct { + common.Response + DiskId string +} + +// ReplaceSystemDisk replace system disk +// +// You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/disk/replacesystemdisk.html +func (client *Client) ReplaceSystemDisk(args *ReplaceSystemDiskArgs) (diskId string, err error) { + response := ReplaceSystemDiskResponse{} + err = client.Invoke("ReplaceSystemDisk", args, &response) + if err != nil { + return "", err + } + return response.DiskId, nil +} + +// WaitForDisk waits for disk to given status +func (client *Client) WaitForDisk(regionId common.Region, diskId string, status DiskStatus, timeout int) error { + if timeout <= 0 { + timeout = DefaultTimeout + } + args := DescribeDisksArgs{ + RegionId: regionId, + DiskIds: []string{diskId}, + } + + for { + disks, _, err := client.DescribeDisks(&args) + if err != nil { + return err + } + if disks == nil || len(disks) == 0 { + return common.GetClientErrorFromString("Not found") + } + if disks[0].Status == status { + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + } + return nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/disks_test.go b/vendor/github.com/denverdino/aliyungo/ecs/disks_test.go new file mode 100644 index 0000000000..e6f7beb833 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/disks_test.go @@ -0,0 +1,151 @@ +package ecs + +import ( + "testing" +) + +func TestDisks(t *testing.T) { + + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := DescribeDisksArgs{} + + args.InstanceId = TestInstanceId + args.RegionId = instance.RegionId + disks, _, err := client.DescribeDisks(&args) + + if err != nil { + t.Fatalf("Failed to DescribeDisks for instance %s: %v", TestInstanceId, err) + } + + for _, disk := range disks { + t.Logf("Disk of instance %s: %++v", TestInstanceId, disk) + } +} + +func TestDiskCreationAndDeletion(t *testing.T) { + + if TestIAmRich == false { //Avoid payment + return + } + + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := CreateDiskArgs{ + RegionId: instance.RegionId, + ZoneId: instance.ZoneId, + DiskName: "test-disk", + Size: 5, + } + + diskId, err := client.CreateDisk(&args) + if err != nil { + t.Fatalf("Failed to create disk: %v", err) + } + t.Logf("Create disk %s successfully", diskId) + + attachArgs := AttachDiskArgs{ + InstanceId: instance.InstanceId, + DiskId: diskId, + } + + err = client.AttachDisk(&attachArgs) + if err != nil { + t.Errorf("Failed to create disk: %v", err) + } else { + t.Logf("Attach disk %s to instance %s successfully", diskId, instance.InstanceId) + + instance, err = client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Errorf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } else { + t.Logf("Instance: %++v %v", instance, err) + } + err = client.WaitForDisk(instance.RegionId, diskId, DiskStatusInUse, 0) + if err != nil { + t.Fatalf("Failed to wait for disk %s to status %s: %v", diskId, DiskStatusInUse, err) + } + err = client.DetachDisk(instance.InstanceId, diskId) + if err != nil { + t.Errorf("Failed to detach disk: %v", err) + } else { + t.Logf("Detach disk %s to instance %s successfully", diskId, instance.InstanceId) + } + + err = client.WaitForDisk(instance.RegionId, diskId, DiskStatusAvailable, 0) + if err != nil { + t.Fatalf("Failed to wait for disk %s to status %s: %v", diskId, DiskStatusAvailable, err) + } + } + err = client.DeleteDisk(diskId) + if err != nil { + t.Fatalf("Failed to delete disk %s: %v", diskId, err) + } + t.Logf("Delete disk %s successfully", diskId) +} + +func TestReplaceSystemDiskUsingSizeParam(t *testing.T) { + client := NewTestClientForDebug() + + args := ReplaceSystemDiskArgs{ + InstanceId: TestInstanceId, + ImageId: TestImageId, + SystemDisk: SystemDiskType{ + Size: 192, + }, + ClientToken: client.GenerateClientToken(), + } + + diskId, err := client.ReplaceSystemDisk(&args) + if err != nil { + t.Errorf("Failed to replace system disk %v", err) + } else { + t.Logf("diskId is %s", diskId) + } +} + +func TestReplaceSystemDisk(t *testing.T) { + client := NewTestClient() + + err := client.WaitForInstance(TestInstanceId, Running, 0) + err = client.StopInstance(TestInstanceId, true) + if err != nil { + t.Errorf("Failed to stop instance %s: %v", TestInstanceId, err) + } + err = client.WaitForInstance(TestInstanceId, Stopped, 0) + if err != nil { + t.Errorf("Instance %s is failed to stop: %v", TestInstanceId, err) + } + t.Logf("Instance %s is stopped successfully.", TestInstanceId) + + args := ReplaceSystemDiskArgs{ + InstanceId: TestInstanceId, + ImageId: TestImageId, + } + + diskId, err := client.ReplaceSystemDisk(&args) + if err != nil { + t.Errorf("Failed to replace system disk %v", err) + } + err = client.WaitForInstance(TestInstanceId, Stopped, 60) + err = client.StartInstance(TestInstanceId) + if err != nil { + t.Errorf("Failed to start instance %s: %v", TestInstanceId, err) + } else { + err = client.WaitForInstance(TestInstanceId, Running, 0) + if err != nil { + t.Errorf("Failed to wait for instance %s running: %v", TestInstanceId, err) + } + } + t.Logf("Replace system disk %s successfully ", diskId) +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/images.go b/vendor/github.com/denverdino/aliyungo/ecs/images.go new file mode 100644 index 0000000000..833489d5bf --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/images.go @@ -0,0 +1,267 @@ +package ecs + +import ( + "net/url" + "strconv" + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +// ImageOwnerAlias represents image owner +type ImageOwnerAlias string + +// Constants of image owner +const ( + ImageOwnerSystem = ImageOwnerAlias("system") + ImageOwnerSelf = ImageOwnerAlias("self") + ImageOwnerOthers = ImageOwnerAlias("others") + ImageOwnerMarketplace = ImageOwnerAlias("marketplace") + ImageOwnerDefault = ImageOwnerAlias("") //Return the values for system, self, and others +) + +type ImageStatus string + +const ( + ImageStatusAvailable = ImageStatus("Available") + ImageStatusUnAvailable = ImageStatus("UnAvailable") + ImageStatusCreating = ImageStatus("Creating") + ImageStatusCreateFailed = ImageStatus("CreateFailed") +) + +// DescribeImagesArgs repsents arguements to describe images +type DescribeImagesArgs struct { + RegionId common.Region + ImageId string + SnapshotId string + ImageName string + Status ImageStatus + ImageOwnerAlias ImageOwnerAlias + common.Pagination +} + +type DescribeImagesResponse struct { + common.Response + common.PaginationResult + + RegionId common.Region + Images struct { + Image []ImageType + } +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&diskdevicemapping +type DiskDeviceMapping struct { + SnapshotId string + //Why Size Field is string-type. + Size string + Device string +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&imagetype +type ImageType struct { + ImageId string + ImageVersion string + Architecture string + ImageName string + Description string + Size int + ImageOwnerAlias string + OSName string + DiskDeviceMappings struct { + DiskDeviceMapping []DiskDeviceMapping + } + ProductCode string + IsSubscribed bool + Progress string + Status ImageStatus + CreationTime util.ISO6801Time +} + +// DescribeImages describes images +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/image&describeimages +func (client *Client) DescribeImages(args *DescribeImagesArgs) (images []ImageType, pagination *common.PaginationResult, err error) { + + args.Validate() + response := DescribeImagesResponse{} + err = client.Invoke("DescribeImages", args, &response) + if err != nil { + return nil, nil, err + } + return response.Images.Image, &response.PaginationResult, nil +} + +// CreateImageArgs repsents arguements to create image +type CreateImageArgs struct { + RegionId common.Region + SnapshotId string + ImageName string + ImageVersion string + Description string + ClientToken string +} + +type CreateImageResponse struct { + common.Response + + ImageId string +} + +// CreateImage creates a new image +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/image&createimage +func (client *Client) CreateImage(args *CreateImageArgs) (imageId string, err error) { + response := &CreateImageResponse{} + err = client.Invoke("CreateImage", args, &response) + if err != nil { + return "", err + } + return response.ImageId, nil +} + +type DeleteImageArgs struct { + RegionId common.Region + ImageId string +} + +type DeleteImageResponse struct { + common.Response +} + +// DeleteImage deletes Image +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/image&deleteimage +func (client *Client) DeleteImage(regionId common.Region, imageId string) error { + args := DeleteImageArgs{ + RegionId: regionId, + ImageId: imageId, + } + + response := &DeleteImageResponse{} + return client.Invoke("DeleteImage", &args, &response) +} + +// ModifyImageSharePermission repsents arguements to share image +type ModifyImageSharePermissionArgs struct { + RegionId common.Region + ImageId string + AddAccount []string + RemoveAccount []string +} + +// You can read doc at http://help.aliyun.com/document_detail/ecs/open-api/image/modifyimagesharepermission.html +func (client *Client) ModifyImageSharePermission(args *ModifyImageSharePermissionArgs) error { + req := url.Values{} + req.Add("RegionId", string(args.RegionId)) + req.Add("ImageId", args.ImageId) + + for i, item := range args.AddAccount { + req.Add("AddAccount."+strconv.Itoa(i+1), item) + } + for i, item := range args.RemoveAccount { + req.Add("RemoveAccount."+strconv.Itoa(i+1), item) + } + + return client.Invoke("ModifyImageSharePermission", req, &common.Response{}) +} + +type AccountType struct { + AliyunId string +} +type ImageSharePermissionResponse struct { + common.Response + ImageId string + RegionId string + Accounts struct { + Account []AccountType + } + TotalCount int + PageNumber int + PageSize int +} + +func (client *Client) DescribeImageSharePermission(args *ModifyImageSharePermissionArgs) (*ImageSharePermissionResponse, error) { + response := ImageSharePermissionResponse{} + err := client.Invoke("DescribeImageSharePermission", args, &response) + return &response, err +} + +type CopyImageArgs struct { + RegionId common.Region + ImageId string + DestinationRegionId common.Region + DestinationImageName string + DestinationDescription string + ClientToken string +} + +type CopyImageResponse struct { + common.Response + ImageId string +} + +// You can read doc at https://help.aliyun.com/document_detail/25538.html +func (client *Client) CopyImage(args *CopyImageArgs) (string, error) { + response := &CopyImageResponse{} + err := client.Invoke("CopyImage", args, &response) + if err != nil { + return "", err + } + return response.ImageId, nil +} + +// Default timeout value for WaitForImageReady method +const ImageDefaultTimeout = 120 + +//Wait Image ready +func (client *Client) WaitForImageReady(regionId common.Region, imageId string, timeout int) error { + if timeout <= 0 { + timeout = ImageDefaultTimeout + } + for { + args := DescribeImagesArgs{ + RegionId: regionId, + ImageId: imageId, + Status: ImageStatusCreating, + } + + images, _, err := client.DescribeImages(&args) + if err != nil { + return err + } + if images == nil || len(images) == 0 { + args.Status = ImageStatusAvailable + images, _, er := client.DescribeImages(&args) + if er == nil && len(images) == 1 { + break + } else { + return common.GetClientErrorFromString("Not found") + } + } + if images[0].Progress == "100%" { + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + } + return nil +} + +type CancelCopyImageRequest struct { + regionId common.Region + ImageId string +} + +// You can read doc at https://help.aliyun.com/document_detail/25539.html +func (client *Client) CancelCopyImage(regionId common.Region, imageId string) error { + response := &common.Response{} + err := client.Invoke("CancelCopyImage", &CancelCopyImageRequest{regionId, imageId}, &response) + return err +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/images_test.go b/vendor/github.com/denverdino/aliyungo/ecs/images_test.go new file mode 100644 index 0000000000..3ebdda9586 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/images_test.go @@ -0,0 +1,114 @@ +package ecs + +import ( + "testing" + + "github.com/denverdino/aliyungo/common" +) + +func TestImageCreationAndDeletion(t *testing.T) { + + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := DescribeSnapshotsArgs{} + + args.InstanceId = TestInstanceId + args.RegionId = instance.RegionId + snapshots, _, err := client.DescribeSnapshots(&args) + + if err != nil { + t.Errorf("Failed to DescribeSnapshots for instance %s: %v", TestInstanceId, err) + } + + if len(snapshots) > 0 { + + createImageArgs := CreateImageArgs{ + RegionId: instance.RegionId, + SnapshotId: snapshots[0].SnapshotId, + + ImageName: "My_Test_Image_for_AliyunGo", + ImageVersion: "1.0", + Description: "My Test Image for AliyunGo description", + ClientToken: client.GenerateClientToken(), + } + imageId, err := client.CreateImage(&createImageArgs) + if err != nil { + t.Errorf("Failed to CreateImage for SnapshotId %s: %v", createImageArgs.SnapshotId, err) + } + t.Logf("Image %s is created successfully.", imageId) + + err = client.DeleteImage(instance.RegionId, imageId) + if err != nil { + t.Errorf("Failed to DeleteImage for %s: %v", imageId, err) + } + t.Logf("Image %s is deleted successfully.", imageId) + + } +} + +func TestModifyImageSharePermission(t *testing.T) { + req := ModifyImageSharePermissionArgs{ + RegionId: common.Beijing, + ImageId: TestImageId, + AddAccount: []string{TestAccountId}, + } + client := NewTestClient() + err := client.ModifyImageSharePermission(&req) + if err != nil { + t.Errorf("Failed to ShareImage: %v", err) + } + + shareInfo, err := client.DescribeImageSharePermission(&req) + if err != nil { + t.Errorf("Failed to ShareImage: %v", err) + } + t.Logf("result:image: %++v", shareInfo) +} + +func TestCopyImage(t *testing.T) { + client := NewTestClient() + req := CopyImageArgs{ + RegionId: common.Beijing, + ImageId: TestImageId, + DestinationRegionId: common.Hangzhou, + DestinationImageName: "My_Test_Image_NAME_for_AliyunGo", + DestinationDescription: "My Test Image for AliyunGo description", + ClientToken: client.GenerateClientToken(), + } + + imageId, err := client.CopyImage(&req) + if err != nil { + t.Errorf("Failed to CopyImage: %v", err) + } + t.Logf("result:image: %++v", imageId) + + if err := client.WaitForImageReady(common.Hangzhou, imageId, 600); err != nil { + t.Errorf("Failed to WaitImage: %v", err) + //return + } + + describeReq := DescribeImagesArgs{ + RegionId: common.Hangzhou, + ImageId: imageId, + Status: ImageStatusAvailable, + ImageOwnerAlias: ImageOwnerSelf, + } + + images, _, err := client.DescribeImages(&describeReq) + if err != nil { + t.Errorf("Failed to describeImage: %v", err) + } + t.Logf("result: images %++v", images) +} + +func TestCancelCopyImage(t *testing.T) { + client := NewTestClient() + if err := client.CancelCopyImage(common.Hangzhou, TestImageId); err != nil { + t.Errorf("Failed to CancelCopyImage: %v", err) + } +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/instance_types.go b/vendor/github.com/denverdino/aliyungo/ecs/instance_types.go new file mode 100644 index 0000000000..ca16822ab8 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/instance_types.go @@ -0,0 +1,37 @@ +package ecs + +import "github.com/denverdino/aliyungo/common" + +type DescribeInstanceTypesArgs struct { +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancetypeitemtype +type InstanceTypeItemType struct { + InstanceTypeId string + CpuCoreCount int + MemorySize float64 + InstanceTypeFamily string +} + +type DescribeInstanceTypesResponse struct { + common.Response + InstanceTypes struct { + InstanceType []InstanceTypeItemType + } +} + +// DescribeInstanceTypes describes all instance types +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/other&describeinstancetypes +func (client *Client) DescribeInstanceTypes() (instanceTypes []InstanceTypeItemType, err error) { + response := DescribeInstanceTypesResponse{} + + err = client.Invoke("DescribeInstanceTypes", &DescribeInstanceTypesArgs{}, &response) + + if err != nil { + return []InstanceTypeItemType{}, err + } + return response.InstanceTypes.InstanceType, nil + +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/instance_types_test.go b/vendor/github.com/denverdino/aliyungo/ecs/instance_types_test.go new file mode 100644 index 0000000000..7aad5677cc --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/instance_types_test.go @@ -0,0 +1,17 @@ +package ecs + +import ( + "testing" +) + +func TestDescribeInstanceTypes(t *testing.T) { + + client := NewTestClient() + instanceTypes, err := client.DescribeInstanceTypes() + if err != nil { + t.Fatalf("Failed to DescribeInstanceTypes: %v", err) + } + for _, instanceType := range instanceTypes { + t.Logf("InstanceType: %++v", instanceType) + } +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/instances.go b/vendor/github.com/denverdino/aliyungo/ecs/instances.go new file mode 100644 index 0000000000..c78cc3de4e --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/instances.go @@ -0,0 +1,492 @@ +package ecs + +import ( + "encoding/base64" + "encoding/json" + "strconv" + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +// InstanceStatus represents instance status +type InstanceStatus string + +// Constants of InstanceStatus +const ( + Creating = InstanceStatus("Creating") + Running = InstanceStatus("Running") + Starting = InstanceStatus("Starting") + + Stopped = InstanceStatus("Stopped") + Stopping = InstanceStatus("Stopping") +) + +type LockReason string + +const ( + LockReasonFinancial = LockReason("financial") + LockReasonSecurity = LockReason("security") +) + +type LockReasonType struct { + LockReason LockReason +} + +type DescribeInstanceStatusArgs struct { + RegionId common.Region + ZoneId string + common.Pagination +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancestatusitemtype +type InstanceStatusItemType struct { + InstanceId string + Status InstanceStatus +} + +type DescribeInstanceStatusResponse struct { + common.Response + common.PaginationResult + InstanceStatuses struct { + InstanceStatus []InstanceStatusItemType + } +} + +// DescribeInstanceStatus describes instance status +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstancestatus +func (client *Client) DescribeInstanceStatus(args *DescribeInstanceStatusArgs) (instanceStatuses []InstanceStatusItemType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeInstanceStatusResponse{} + + err = client.Invoke("DescribeInstanceStatus", args, &response) + + if err == nil { + return response.InstanceStatuses.InstanceStatus, &response.PaginationResult, nil + } + + return nil, nil, err +} + +type StopInstanceArgs struct { + InstanceId string + ForceStop bool +} + +type StopInstanceResponse struct { + common.Response +} + +// StopInstance stops instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&stopinstance +func (client *Client) StopInstance(instanceId string, forceStop bool) error { + args := StopInstanceArgs{ + InstanceId: instanceId, + ForceStop: forceStop, + } + response := StopInstanceResponse{} + err := client.Invoke("StopInstance", &args, &response) + return err +} + +type StartInstanceArgs struct { + InstanceId string +} + +type StartInstanceResponse struct { + common.Response +} + +// StartInstance starts instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&startinstance +func (client *Client) StartInstance(instanceId string) error { + args := StartInstanceArgs{InstanceId: instanceId} + response := StartInstanceResponse{} + err := client.Invoke("StartInstance", &args, &response) + return err +} + +type RebootInstanceArgs struct { + InstanceId string + ForceStop bool +} + +type RebootInstanceResponse struct { + common.Response +} + +// RebootInstance reboot instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&rebootinstance +func (client *Client) RebootInstance(instanceId string, forceStop bool) error { + request := RebootInstanceArgs{ + InstanceId: instanceId, + ForceStop: forceStop, + } + response := RebootInstanceResponse{} + err := client.Invoke("RebootInstance", &request, &response) + return err +} + +type DescribeInstanceAttributeArgs struct { + InstanceId string +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&operationlockstype +type OperationLocksType struct { + LockReason []LockReasonType //enum for financial, security +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&securitygroupidsettype +type SecurityGroupIdSetType struct { + SecurityGroupId string +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&ipaddresssettype +type IpAddressSetType struct { + IpAddress []string +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&vpcattributestype +type VpcAttributesType struct { + VpcId string + VSwitchId string + PrivateIpAddress IpAddressSetType + NatIpAddress string +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&eipaddressassociatetype +type EipAddressAssociateType struct { + AllocationId string + IpAddress string + Bandwidth int + InternetChargeType common.InternetChargeType +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instanceattributestype +type InstanceAttributesType struct { + InstanceId string + InstanceName string + Description string + ImageId string + RegionId common.Region + ZoneId string + CPU int + Memory int + ClusterId string + InstanceType string + InstanceTypeFamily string + HostName string + SerialNumber string + Status InstanceStatus + OperationLocks OperationLocksType + SecurityGroupIds struct { + SecurityGroupId []string + } + PublicIpAddress IpAddressSetType + InnerIpAddress IpAddressSetType + InstanceNetworkType string //enum Classic | Vpc + InternetMaxBandwidthIn int + InternetMaxBandwidthOut int + InternetChargeType common.InternetChargeType + CreationTime util.ISO6801Time //time.Time + VpcAttributes VpcAttributesType + EipAddress EipAddressAssociateType + IoOptimized StringOrBool + InstanceChargeType common.InstanceChargeType + ExpiredTime util.ISO6801Time + Tags struct { + Tag []TagItemType + } +} + +type DescribeInstanceAttributeResponse struct { + common.Response + InstanceAttributesType +} + +// DescribeInstanceAttribute describes instance attribute +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstanceattribute +func (client *Client) DescribeInstanceAttribute(instanceId string) (instance *InstanceAttributesType, err error) { + args := DescribeInstanceAttributeArgs{InstanceId: instanceId} + + response := DescribeInstanceAttributeResponse{} + err = client.Invoke("DescribeInstanceAttribute", &args, &response) + if err != nil { + return nil, err + } + return &response.InstanceAttributesType, err +} + +type ModifyInstanceAttributeArgs struct { + InstanceId string + InstanceName string + Description string + Password string + HostName string +} + +type ModifyInstanceAttributeResponse struct { + common.Response +} + +//ModifyInstanceAttribute modify instance attrbute +// +// You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/modifyinstanceattribute.html +func (client *Client) ModifyInstanceAttribute(args *ModifyInstanceAttributeArgs) error { + response := ModifyInstanceAttributeResponse{} + err := client.Invoke("ModifyInstanceAttribute", args, &response) + return err +} + +// Default timeout value for WaitForInstance method +const InstanceDefaultTimeout = 120 + +// WaitForInstance waits for instance to given status +func (client *Client) WaitForInstance(instanceId string, status InstanceStatus, timeout int) error { + if timeout <= 0 { + timeout = InstanceDefaultTimeout + } + for { + instance, err := client.DescribeInstanceAttribute(instanceId) + if err != nil { + return err + } + if instance.Status == status { + //TODO + //Sleep one more time for timing issues + time.Sleep(DefaultWaitForInterval * time.Second) + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + + } + return nil +} + +type DescribeInstanceVncUrlArgs struct { + RegionId common.Region + InstanceId string +} + +type DescribeInstanceVncUrlResponse struct { + common.Response + VncUrl string +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstancevncurl +func (client *Client) DescribeInstanceVncUrl(args *DescribeInstanceVncUrlArgs) (string, error) { + response := DescribeInstanceVncUrlResponse{} + + err := client.Invoke("DescribeInstanceVncUrl", args, &response) + + if err == nil { + return response.VncUrl, nil + } + + return "", err +} + +type DescribeInstancesArgs struct { + RegionId common.Region + VpcId string + VSwitchId string + ZoneId string + InstanceIds string + InstanceNetworkType string + InstanceName string + Status InstanceStatus + PrivateIpAddresses string + InnerIpAddresses string + PublicIpAddresses string + SecurityGroupId string + Tag map[string]string + common.Pagination +} + +type DescribeInstancesResponse struct { + common.Response + common.PaginationResult + Instances struct { + Instance []InstanceAttributesType + } +} + +// DescribeInstances describes instances +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&describeinstances +func (client *Client) DescribeInstances(args *DescribeInstancesArgs) (instances []InstanceAttributesType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeInstancesResponse{} + + err = client.Invoke("DescribeInstances", args, &response) + + if err == nil { + return response.Instances.Instance, &response.PaginationResult, nil + } + + return nil, nil, err +} + +type DeleteInstanceArgs struct { + InstanceId string +} + +type DeleteInstanceResponse struct { + common.Response +} + +// DeleteInstance deletes instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&deleteinstance +func (client *Client) DeleteInstance(instanceId string) error { + args := DeleteInstanceArgs{InstanceId: instanceId} + response := DeleteInstanceResponse{} + err := client.Invoke("DeleteInstance", &args, &response) + return err +} + +type DataDiskType struct { + Size int + Category DiskCategory //Enum cloud, ephemeral, ephemeral_ssd + SnapshotId string + DiskName string + Description string + Device string + DeleteWithInstance bool +} + +type SystemDiskType struct { + Size int + Category DiskCategory //Enum cloud, ephemeral, ephemeral_ssd + DiskName string + Description string +} + +type IoOptimized string + +type StringOrBool struct { + Value bool +} + +// UnmarshalJSON implements the json.Unmarshaller interface. +func (io *StringOrBool) UnmarshalJSON(value []byte) error { + if value[0] == '"' { + var str string + err := json.Unmarshal(value, &str) + if err == nil { + io.Value = (str == "true" || str == "optimized") + } + return err + } + var boolVal bool + err := json.Unmarshal(value, &boolVal) + if err == nil { + io.Value = boolVal + } + return err +} + +func (io StringOrBool) Bool() bool { + return io.Value +} + +func (io StringOrBool) String() string { + return strconv.FormatBool(io.Value) +} + +var ( + IoOptimizedNone = IoOptimized("none") + IoOptimizedOptimized = IoOptimized("optimized") +) + +type CreateInstanceArgs struct { + RegionId common.Region + ZoneId string + ImageId string + InstanceType string + SecurityGroupId string + InstanceName string + Description string + InternetChargeType common.InternetChargeType + InternetMaxBandwidthIn int + InternetMaxBandwidthOut int + HostName string + Password string + IoOptimized IoOptimized + SystemDisk SystemDiskType + DataDisk []DataDiskType + VSwitchId string + PrivateIpAddress string + ClientToken string + InstanceChargeType common.InstanceChargeType + Period int + UserData string +} + +type CreateInstanceResponse struct { + common.Response + InstanceId string +} + +// CreateInstance creates instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/instance&createinstance +func (client *Client) CreateInstance(args *CreateInstanceArgs) (instanceId string, err error) { + if args.UserData != "" { + // Encode to base64 string + args.UserData = base64.StdEncoding.EncodeToString([]byte(args.UserData)) + } + response := CreateInstanceResponse{} + err = client.Invoke("CreateInstance", args, &response) + if err != nil { + return "", err + } + return response.InstanceId, err +} + +type SecurityGroupArgs struct { + InstanceId string + SecurityGroupId string +} + +type SecurityGroupResponse struct { + common.Response +} + +//JoinSecurityGroup +// +//You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/joinsecuritygroup.html +func (client *Client) JoinSecurityGroup(instanceId string, securityGroupId string) error { + args := SecurityGroupArgs{InstanceId: instanceId, SecurityGroupId: securityGroupId} + response := SecurityGroupResponse{} + err := client.Invoke("JoinSecurityGroup", &args, &response) + return err +} + +//LeaveSecurityGroup +// +//You can read doc at https://help.aliyun.com/document_detail/ecs/open-api/instance/leavesecuritygroup.html +func (client *Client) LeaveSecurityGroup(instanceId string, securityGroupId string) error { + args := SecurityGroupArgs{InstanceId: instanceId, SecurityGroupId: securityGroupId} + response := SecurityGroupResponse{} + err := client.Invoke("LeaveSecurityGroup", &args, &response) + return err +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/instances_test.go b/vendor/github.com/denverdino/aliyungo/ecs/instances_test.go new file mode 100644 index 0000000000..6867c86cf5 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/instances_test.go @@ -0,0 +1,252 @@ +package ecs + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/denverdino/aliyungo/common" +) + +func ExampleClient_DescribeInstanceStatus() { + fmt.Printf("DescribeInstanceStatus Example\n") + + args := DescribeInstanceStatusArgs{ + RegionId: "cn-beijing", + ZoneId: "cn-beijing-b", + Pagination: common.Pagination{ + PageNumber: 1, + PageSize: 1, + }, + } + + client := NewTestClient() + instanceStatus, _, err := client.DescribeInstanceStatus(&args) + + if err != nil { + fmt.Printf("Failed to describe Instance: %s status:%v \n", TestInstanceId, err) + } else { + for i := 0; i < len(instanceStatus); i++ { + fmt.Printf("Instance %s Status: %s \n", instanceStatus[i].InstanceId, instanceStatus[i].Status) + } + } +} + +func ExampleClient_DescribeInstanceAttribute() { + fmt.Printf("DescribeInstanceAttribute Example\n") + + client := NewTestClient() + + instanceAttributeType, err := client.DescribeInstanceAttribute(TestInstanceId) + + if err != nil { + fmt.Printf("Failed to describe Instance %s attribute: %v\n", TestInstanceId, err) + } else { + fmt.Printf("Instance Information\n") + fmt.Printf("InstanceId = %s \n", instanceAttributeType.InstanceId) + fmt.Printf("InstanceName = %s \n", instanceAttributeType.InstanceName) + fmt.Printf("HostName = %s \n", instanceAttributeType.HostName) + fmt.Printf("ZoneId = %s \n", instanceAttributeType.ZoneId) + fmt.Printf("RegionId = %s \n", instanceAttributeType.RegionId) + } +} + +func ExampleClient_DescribeInstanceVncUrl() { + fmt.Printf("DescribeInstanceVncUrl Example\n") + + args := DescribeInstanceVncUrlArgs{ + RegionId: "cn-beijing", + InstanceId: TestInstanceId, + } + + client := NewTestClient() + + instanceVncUrl, err := client.DescribeInstanceVncUrl(&args) + + if err != nil { + fmt.Printf("Failed to describe Instance %s vnc url: %v \n", TestInstanceId, err) + } else { + fmt.Printf("VNC URL = %s \n", instanceVncUrl) + } +} + +func ExampleClient_StopInstance() { + fmt.Printf("Stop Instance Example\n") + + client := NewTestClient() + + err := client.StopInstance(TestInstanceId, true) + + if err != nil { + fmt.Printf("Failed to stop Instance %s vnc url: %v \n", TestInstanceId, err) + } +} + +func ExampleClient_DeleteInstance() { + fmt.Printf("Delete Instance Example") + + client := NewTestClient() + + err := client.DeleteInstance(TestInstanceId) + + if err != nil { + fmt.Printf("Failed to delete Instance %s vnc url: %v \n", TestInstanceId, err) + } +} + +func TestECSInstance(t *testing.T) { + if TestQuick { + return + } + client := NewTestClient() + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to describe instance %s: %v", TestInstanceId, err) + } + t.Logf("Instance: %++v %v", instance, err) + err = client.StopInstance(TestInstanceId, true) + if err != nil { + t.Errorf("Failed to stop instance %s: %v", TestInstanceId, err) + } + err = client.WaitForInstance(TestInstanceId, Stopped, 0) + if err != nil { + t.Errorf("Instance %s is failed to stop: %v", TestInstanceId, err) + } + t.Logf("Instance %s is stopped successfully.", TestInstanceId) + err = client.StartInstance(TestInstanceId) + if err != nil { + t.Errorf("Failed to start instance %s: %v", TestInstanceId, err) + } + err = client.WaitForInstance(TestInstanceId, Running, 0) + if err != nil { + t.Errorf("Instance %s is failed to start: %v", TestInstanceId, err) + } + t.Logf("Instance %s is running successfully.", TestInstanceId) + err = client.RebootInstance(TestInstanceId, true) + if err != nil { + t.Errorf("Failed to restart instance %s: %v", TestInstanceId, err) + } + err = client.WaitForInstance(TestInstanceId, Running, 0) + if err != nil { + t.Errorf("Instance %s is failed to restart: %v", TestInstanceId, err) + } + t.Logf("Instance %s is running successfully.", TestInstanceId) +} + +func TestECSInstanceCreationAndDeletion(t *testing.T) { + + if TestIAmRich == false { // Avoid payment + return + } + + client := NewTestClient() + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + t.Logf("Instance: %++v %v", instance, err) + + args := CreateInstanceArgs{ + RegionId: instance.RegionId, + ImageId: instance.ImageId, + InstanceType: "ecs.t1.small", + SecurityGroupId: instance.SecurityGroupIds.SecurityGroupId[0], + } + + instanceId, err := client.CreateInstance(&args) + if err != nil { + t.Errorf("Failed to create instance from Image %s: %v", args.ImageId, err) + } + t.Logf("Instance %s is created successfully.", instanceId) + + instance, err = client.DescribeInstanceAttribute(instanceId) + t.Logf("Instance: %++v %v", instance, err) + + err = client.WaitForInstance(instanceId, Stopped, 60) + + err = client.StartInstance(instanceId) + if err != nil { + t.Errorf("Failed to start instance %s: %v", instanceId, err) + } + err = client.WaitForInstance(instanceId, Running, 0) + + err = client.StopInstance(instanceId, true) + if err != nil { + t.Errorf("Failed to stop instance %s: %v", instanceId, err) + } + err = client.WaitForInstance(instanceId, Stopped, 0) + if err != nil { + t.Errorf("Instance %s is failed to stop: %v", instanceId, err) + } + t.Logf("Instance %s is stopped successfully.", instanceId) + + err = client.DeleteInstance(instanceId) + + if err != nil { + t.Errorf("Failed to delete instance %s: %v", instanceId, err) + } + t.Logf("Instance %s is deleted successfully.", instanceId) +} + +func TestModifyInstanceAttribute(t *testing.T) { + client := NewTestClient() + + args := ModifyInstanceAttributeArgs{ + InstanceId: TestInstanceId, + Password: "Just$test", + } + + err := client.ModifyInstanceAttribute(&args) + if err != nil { + t.Errorf("Failed to modify instance attribute %s: %v", TestInstanceId, err) + } + + t.Logf("Modify instance attribute successfully") +} + +func TestIoOptimized(t *testing.T) { + + type TestStruct struct { + Str string + Flag StringOrBool + } + + var test TestStruct + + txt := "{\"Str\":\"abc\", \"Flag\": true}" + + err := json.Unmarshal([]byte(txt), &test) + if err != nil { + t.Errorf("Failed to Unmarshal IoOptimized: %v", err) + } else { + if test.Flag.Value != true { + t.Errorf("Failed to Unmarshal IoOptimized with expected value: %s", test.Flag) + } + } + + txt1 := "{\"Str\":\"abc\", \"Flag\": \"false\"}" + + err = json.Unmarshal([]byte(txt1), &test) + if err != nil { + t.Errorf("Failed to Unmarshal IoOptimized: %v", err) + } else { + if test.Flag.Value != false { + t.Errorf("Failed to Unmarshal IoOptimized with expected value: %s", test.Flag) + } + } +} + +func TestJoinSecurityGroup(t *testing.T) { + client := NewTestClient() + + err := client.JoinSecurityGroup(TestInstanceId, TestSecurityGroupId) + if err != nil { + t.Errorf("Failed to joinSecurityGroup: %v", err) + } +} + +func TestLeaveSecurityGroup(t *testing.T) { + client := NewTestClient() + + err := client.LeaveSecurityGroup(TestInstanceId, TestSecurityGroupId) + if err != nil { + t.Errorf("Failed to LeaveSecurityGroup: %v", err) + } +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/monitoring.go b/vendor/github.com/denverdino/aliyungo/ecs/monitoring.go new file mode 100644 index 0000000000..6123d28b71 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/monitoring.go @@ -0,0 +1,136 @@ +package ecs + +import ( + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type DescribeInstanceMonitorDataArgs struct { + InstanceId string + StartTime util.ISO6801Time + EndTime util.ISO6801Time + Period int //Default 60s +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&instancemonitordatatype +type InstanceMonitorDataType struct { + InstanceId string + CPU int + IntranetRX int + IntranetTX int + IntranetBandwidth int + InternetRX int + InternetTX int + InternetBandwidth int + IOPSRead int + IOPSWrite int + BPSRead int + BPSWrite int + TimeStamp util.ISO6801Time +} + +type DescribeInstanceMonitorDataResponse struct { + common.Response + MonitorData struct { + InstanceMonitorData []InstanceMonitorDataType + } +} + +// DescribeInstanceMonitorData describes instance monitoring data +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/monitor&describeinstancemonitordata +func (client *Client) DescribeInstanceMonitorData(args *DescribeInstanceMonitorDataArgs) (monitorData []InstanceMonitorDataType, err error) { + if args.Period == 0 { + args.Period = 60 + } + response := DescribeInstanceMonitorDataResponse{} + err = client.Invoke("DescribeInstanceMonitorData", args, &response) + if err != nil { + return nil, err + } + return response.MonitorData.InstanceMonitorData, err +} + +type DescribeEipMonitorDataArgs struct { + AllocationId string + StartTime util.ISO6801Time + EndTime util.ISO6801Time + Period int //Default 60s +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&eipmonitordatatype +type EipMonitorDataType struct { + EipRX int + EipTX int + EipFlow int + EipBandwidth int + EipPackets int + TimeStamp util.ISO6801Time +} + +type DescribeEipMonitorDataResponse struct { + common.Response + EipMonitorDatas struct { + EipMonitorData []EipMonitorDataType + } +} + +// DescribeEipMonitorData describes EIP monitoring data +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/monitor&describeeipmonitordata +func (client *Client) DescribeEipMonitorData(args *DescribeEipMonitorDataArgs) (monitorData []EipMonitorDataType, err error) { + if args.Period == 0 { + args.Period = 60 + } + response := DescribeEipMonitorDataResponse{} + err = client.Invoke("DescribeEipMonitorData", args, &response) + if err != nil { + return nil, err + } + return response.EipMonitorDatas.EipMonitorData, err +} + +type DescribeDiskMonitorDataArgs struct { + DiskId string + StartTime util.ISO6801Time + EndTime util.ISO6801Time + Period int //Default 60s +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&diskmonitordatatype +type DiskMonitorDataType struct { + DiskId string + IOPSRead int + IOPSWrite int + IOPSTotal int + BPSRead int + BPSWrite int + BPSTotal int + TimeStamp util.ISO6801Time +} + +type DescribeDiskMonitorDataResponse struct { + common.Response + TotalCount int + MonitorData struct { + DiskMonitorData []DiskMonitorDataType + } +} + +// DescribeDiskMonitorData describes disk monitoring data +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/monitor&describediskmonitordata +func (client *Client) DescribeDiskMonitorData(args *DescribeDiskMonitorDataArgs) (monitorData []DiskMonitorDataType, totalCount int, err error) { + if args.Period == 0 { + args.Period = 60 + } + response := DescribeDiskMonitorDataResponse{} + err = client.Invoke("DescribeDiskMonitorData", args, &response) + if err != nil { + return nil, 0, err + } + return response.MonitorData.DiskMonitorData, response.TotalCount, err +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/monitoring_test.go b/vendor/github.com/denverdino/aliyungo/ecs/monitoring_test.go new file mode 100644 index 0000000000..ef53c0495a --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/monitoring_test.go @@ -0,0 +1,71 @@ +package ecs + +import ( + "testing" + "time" + + "github.com/denverdino/aliyungo/util" +) + +func TestMonitoring(t *testing.T) { + client := NewTestClient() + //client.SetDebug(true) + + //Describe test instance + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to describe instance %s: %v", TestInstanceId, err) + } + t.Logf("Instance: %++v %v", instance, err) + + //Describe Instance Monitor Data + now := time.Now().UTC() + + starting := time.Date(now.Year(), now.Month(), now.Day(), now.Hour()-2, now.Minute(), now.Second(), now.Nanosecond(), now.Location()) + ending := time.Date(now.Year(), now.Month(), now.Day(), now.Hour()-1, now.Minute(), now.Second(), now.Nanosecond(), now.Location()) + + args := DescribeInstanceMonitorDataArgs{ + InstanceId: TestInstanceId, + StartTime: util.ISO6801Time(starting), + EndTime: util.ISO6801Time(ending), + } + + monitorData, err := client.DescribeInstanceMonitorData(&args) + + if err != nil { + t.Fatalf("Failed to describe monitoring data for instance %s: %v", TestInstanceId, err) + } + + for _, data := range monitorData { + t.Logf("Monitor Data: %++v", data) + } + //Describe EIP monitor data + + //Describe disk monitor data + diskArgs := DescribeDisksArgs{ + InstanceId: TestInstanceId, + RegionId: instance.RegionId, + } + + disks, _, err := client.DescribeDisks(&diskArgs) + if err != nil { + t.Fatalf("Failed to DescribeDisks for instance %s: %v", TestInstanceId, err) + } + + for _, disk := range disks { + args := DescribeDiskMonitorDataArgs{ + DiskId: disk.DiskId, + StartTime: util.ISO6801Time(starting), + EndTime: util.ISO6801Time(ending), + } + monitorData, _, err := client.DescribeDiskMonitorData(&args) + + if err != nil { + t.Fatalf("Failed to describe monitoring data for disk %s: %v", disk.DiskId, err) + } + + for _, data := range monitorData { + t.Logf("Monitor Data: %++v", data) + } + } +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/networks.go b/vendor/github.com/denverdino/aliyungo/ecs/networks.go new file mode 100644 index 0000000000..fecc7af1a0 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/networks.go @@ -0,0 +1,249 @@ +// API on Network + +package ecs + +import ( + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type AllocatePublicIpAddressArgs struct { + InstanceId string +} + +type AllocatePublicIpAddressResponse struct { + common.Response + + IpAddress string +} + +// AllocatePublicIpAddress allocates Public Ip Address +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&allocatepublicipaddress +func (client *Client) AllocatePublicIpAddress(instanceId string) (ipAddress string, err error) { + args := AllocatePublicIpAddressArgs{ + InstanceId: instanceId, + } + response := AllocatePublicIpAddressResponse{} + err = client.Invoke("AllocatePublicIpAddress", &args, &response) + if err != nil { + return "", err + } + return response.IpAddress, nil +} + +type ModifyInstanceNetworkSpec struct { + InstanceId string + InternetMaxBandwidthOut *int + InternetMaxBandwidthIn *int +} + +type ModifyInstanceNetworkSpecResponse struct { + common.Response +} + +// ModifyInstanceNetworkSpec modifies instance network spec +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&modifyinstancenetworkspec +func (client *Client) ModifyInstanceNetworkSpec(args *ModifyInstanceNetworkSpec) error { + + response := ModifyInstanceNetworkSpecResponse{} + return client.Invoke("ModifyInstanceNetworkSpec", args, &response) +} + +type AllocateEipAddressArgs struct { + RegionId common.Region + Bandwidth int + InternetChargeType common.InternetChargeType + ClientToken string +} + +type AllocateEipAddressResponse struct { + common.Response + EipAddress string + AllocationId string +} + +// AllocateEipAddress allocates Eip Address +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&allocateeipaddress +func (client *Client) AllocateEipAddress(args *AllocateEipAddressArgs) (EipAddress string, AllocationId string, err error) { + if args.Bandwidth == 0 { + args.Bandwidth = 5 + } + response := AllocateEipAddressResponse{} + err = client.Invoke("AllocateEipAddress", args, &response) + if err != nil { + return "", "", err + } + return response.EipAddress, response.AllocationId, nil +} + +type AssociateEipAddressArgs struct { + AllocationId string + InstanceId string +} + +type AssociateEipAddressResponse struct { + common.Response +} + +// AssociateEipAddress associates EIP address to VM instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&associateeipaddress +func (client *Client) AssociateEipAddress(allocationId string, instanceId string) error { + args := AssociateEipAddressArgs{ + AllocationId: allocationId, + InstanceId: instanceId, + } + response := ModifyInstanceNetworkSpecResponse{} + return client.Invoke("AssociateEipAddress", &args, &response) +} + +// Status of disks +type EipStatus string + +const ( + EipStatusAssociating = EipStatus("Associating") + EipStatusUnassociating = EipStatus("Unassociating") + EipStatusInUse = EipStatus("InUse") + EipStatusAvailable = EipStatus("Available") +) + +type DescribeEipAddressesArgs struct { + RegionId common.Region + Status EipStatus //enum Associating | Unassociating | InUse | Available + EipAddress string + AllocationId string + common.Pagination +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&eipaddresssettype +type EipAddressSetType struct { + RegionId common.Region + IpAddress string + AllocationId string + Status EipStatus + InstanceId string + Bandwidth string // Why string + InternetChargeType common.InternetChargeType + OperationLocks OperationLocksType + AllocationTime util.ISO6801Time +} + +type DescribeEipAddressesResponse struct { + common.Response + common.PaginationResult + EipAddresses struct { + EipAddress []EipAddressSetType + } +} + +// DescribeInstanceStatus describes instance status +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&describeeipaddresses +func (client *Client) DescribeEipAddresses(args *DescribeEipAddressesArgs) (eipAddresses []EipAddressSetType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeEipAddressesResponse{} + + err = client.Invoke("DescribeEipAddresses", args, &response) + + if err == nil { + return response.EipAddresses.EipAddress, &response.PaginationResult, nil + } + + return nil, nil, err +} + +type ModifyEipAddressAttributeArgs struct { + AllocationId string + Bandwidth int +} + +type ModifyEipAddressAttributeResponse struct { + common.Response +} + +// ModifyEipAddressAttribute Modifies EIP attribute +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&modifyeipaddressattribute +func (client *Client) ModifyEipAddressAttribute(allocationId string, bandwidth int) error { + args := ModifyEipAddressAttributeArgs{ + AllocationId: allocationId, + Bandwidth: bandwidth, + } + response := ModifyEipAddressAttributeResponse{} + return client.Invoke("ModifyEipAddressAttribute", &args, &response) +} + +type UnallocateEipAddressArgs struct { + AllocationId string + InstanceId string +} + +type UnallocateEipAddressResponse struct { + common.Response +} + +// UnassociateEipAddress unallocates Eip Address from instance +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&unassociateeipaddress +func (client *Client) UnassociateEipAddress(allocationId string, instanceId string) error { + args := UnallocateEipAddressArgs{ + AllocationId: allocationId, + InstanceId: instanceId, + } + response := UnallocateEipAddressResponse{} + return client.Invoke("UnassociateEipAddress", &args, &response) +} + +type ReleaseEipAddressArgs struct { + AllocationId string +} + +type ReleaseEipAddressResponse struct { + common.Response +} + +// ReleaseEipAddress releases Eip address +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/network&releaseeipaddress +func (client *Client) ReleaseEipAddress(allocationId string) error { + args := ReleaseEipAddressArgs{ + AllocationId: allocationId, + } + response := ReleaseEipAddressResponse{} + return client.Invoke("ReleaseEipAddress", &args, &response) +} + +// WaitForVSwitchAvailable waits for VSwitch to given status +func (client *Client) WaitForEip(regionId common.Region, allocationId string, status EipStatus, timeout int) error { + if timeout <= 0 { + timeout = DefaultTimeout + } + args := DescribeEipAddressesArgs{ + RegionId: regionId, + AllocationId: allocationId, + } + for { + eips, _, err := client.DescribeEipAddresses(&args) + if err != nil { + return err + } + if len(eips) == 0 { + return common.GetClientErrorFromString("Not found") + } + if eips[0].Status == status { + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + } + return nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/networks_test.go b/vendor/github.com/denverdino/aliyungo/ecs/networks_test.go new file mode 100644 index 0000000000..d640d2bf76 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/networks_test.go @@ -0,0 +1,66 @@ +package ecs + +import ( + "testing" + + "github.com/denverdino/aliyungo/common" +) + +func TestAllocatePublicIpAddress(t *testing.T) { + + client := NewTestClient() + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to describe instance %s: %v", TestInstanceId, err) + } + t.Logf("Instance: %++v %v", instance, err) + ipAddr, err := client.AllocatePublicIpAddress(TestInstanceId) + if err != nil { + t.Fatalf("Failed to allocate public IP address for instance %s: %v", TestInstanceId, err) + } + t.Logf("Public IP address of instance %s: %s", TestInstanceId, ipAddr) + +} + +func testEipAddress(t *testing.T, client *Client, regionId common.Region, instanceId string) error { + + args := AllocateEipAddressArgs{ + RegionId: regionId, + Bandwidth: 5, + InternetChargeType: common.PayByTraffic, + ClientToken: client.GenerateClientToken(), + } + ipAddr, allocationId, err := client.AllocateEipAddress(&args) + if err != nil { + t.Errorf("Failed to allocate EIP address: %v", err) + return err + } + t.Logf("EIP address: %s, AllocationId: %s", ipAddr, allocationId) + + err = client.WaitForEip(regionId, allocationId, EipStatusAvailable, 0) + if err != nil { + t.Errorf("Failed to wait EIP %s: %v", allocationId, err) + } + + err = client.AssociateEipAddress(allocationId, instanceId) + if err != nil { + t.Errorf("Failed to associate EIP address: %v", err) + } + err = client.WaitForEip(regionId, allocationId, EipStatusInUse, 0) + if err != nil { + t.Errorf("Failed to wait EIP %s: %v", allocationId, err) + } + err = client.UnassociateEipAddress(allocationId, instanceId) + if err != nil { + t.Errorf("Failed to unassociate EIP address: %v", err) + } + err = client.WaitForEip(regionId, allocationId, EipStatusAvailable, 0) + if err != nil { + t.Errorf("Failed to wait EIP %s: %v", allocationId, err) + } + err = client.ReleaseEipAddress(allocationId) + if err != nil { + t.Errorf("Failed to release EIP address: %v", err) + } + return err +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/regions.go b/vendor/github.com/denverdino/aliyungo/ecs/regions.go new file mode 100644 index 0000000000..d8ed72e8d3 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/regions.go @@ -0,0 +1,34 @@ +package ecs + +import "github.com/denverdino/aliyungo/common" + +type DescribeRegionsArgs struct { +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype®iontype +type RegionType struct { + RegionId common.Region + LocalName string +} + +type DescribeRegionsResponse struct { + common.Response + Regions struct { + Region []RegionType + } +} + +// DescribeRegions describes regions +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/region&describeregions +func (client *Client) DescribeRegions() (regions []RegionType, err error) { + response := DescribeRegionsResponse{} + + err = client.Invoke("DescribeRegions", &DescribeRegionsArgs{}, &response) + + if err != nil { + return []RegionType{}, err + } + return response.Regions.Region, nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/route_tables.go b/vendor/github.com/denverdino/aliyungo/ecs/route_tables.go new file mode 100644 index 0000000000..586fdd8e6e --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/route_tables.go @@ -0,0 +1,162 @@ +package ecs + +import ( + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type DescribeRouteTablesArgs struct { + VRouterId string + RouteTableId string + common.Pagination +} + +type RouteTableType string + +const ( + RouteTableSystem = RouteTableType("System") + RouteTableCustom = RouteTableType("Custom") +) + +type RouteEntryStatus string + +const ( + RouteEntryStatusPending = RouteEntryStatus("Pending") + RouteEntryStatusAvailable = RouteEntryStatus("Available") + RouteEntryStatusModifying = RouteEntryStatus("Modifying") +) + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&routeentrysettype +type RouteEntrySetType struct { + RouteTableId string + DestinationCidrBlock string + Type RouteTableType + InstanceId string + Status RouteEntryStatus // enum Pending | Available | Modifying +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&routetablesettype +type RouteTableSetType struct { + VRouterId string + RouteTableId string + RouteEntrys struct { + RouteEntry []RouteEntrySetType + } + RouteTableType RouteTableType + CreationTime util.ISO6801Time +} + +type DescribeRouteTablesResponse struct { + common.Response + common.PaginationResult + RouteTables struct { + RouteTable []RouteTableSetType + } +} + +// DescribeRouteTables describes Virtual Routers +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/routertable&describeroutetables +func (client *Client) DescribeRouteTables(args *DescribeRouteTablesArgs) (routeTables []RouteTableSetType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeRouteTablesResponse{} + + err = client.Invoke("DescribeRouteTables", args, &response) + + if err == nil { + return response.RouteTables.RouteTable, &response.PaginationResult, nil + } + + return nil, nil, err +} + +type NextHopType string + +const ( + NextHopIntance = NextHopType("Instance") //Default + NextHopTunnel = NextHopType("Tunnel") +) + +type CreateRouteEntryArgs struct { + RouteTableId string + DestinationCidrBlock string + NextHopType NextHopType + NextHopId string + ClientToken string +} + +type CreateRouteEntryResponse struct { + common.Response +} + +// CreateRouteEntry creates route entry +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/routertable&createrouteentry +func (client *Client) CreateRouteEntry(args *CreateRouteEntryArgs) error { + response := CreateRouteEntryResponse{} + return client.Invoke("CreateRouteEntry", args, &response) +} + +type DeleteRouteEntryArgs struct { + RouteTableId string + DestinationCidrBlock string + NextHopId string +} + +type DeleteRouteEntryResponse struct { + common.Response +} + +// DeleteRouteEntry deletes route entry +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/routertable&deleterouteentry +func (client *Client) DeleteRouteEntry(args *DeleteRouteEntryArgs) error { + response := DeleteRouteEntryResponse{} + return client.Invoke("DeleteRouteEntry", args, &response) +} + +// WaitForAllRouteEntriesAvailable waits for all route entries to Available status +func (client *Client) WaitForAllRouteEntriesAvailable(vrouterId string, routeTableId string, timeout int) error { + if timeout <= 0 { + timeout = DefaultTimeout + } + args := DescribeRouteTablesArgs{ + VRouterId: vrouterId, + RouteTableId: routeTableId, + } + for { + + routeTables, _, err := client.DescribeRouteTables(&args) + + if err != nil { + return err + } + if len(routeTables) == 0 { + return common.GetClientErrorFromString("Not found") + } + success := true + + loop: + for _, routeTable := range routeTables { + for _, routeEntry := range routeTable.RouteEntrys.RouteEntry { + if routeEntry.Status != RouteEntryStatusAvailable { + success = false + break loop + } + } + } + if success { + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + } + return nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/route_tables_test.go b/vendor/github.com/denverdino/aliyungo/ecs/route_tables_test.go new file mode 100644 index 0000000000..e0fe17200b --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/route_tables_test.go @@ -0,0 +1,51 @@ +package ecs + +import ( + "testing" + + "github.com/denverdino/aliyungo/common" +) + +func testRouteTable(t *testing.T, client *Client, regionId common.Region, vpcId string, vrouterId string, routeTableId string, instanceId string) { + cidrBlock := "0.0.0.0/0" + createArgs := CreateRouteEntryArgs{ + RouteTableId: routeTableId, + DestinationCidrBlock: cidrBlock, + NextHopType: NextHopIntance, + NextHopId: instanceId, + ClientToken: client.GenerateClientToken(), + } + + err := client.CreateRouteEntry(&createArgs) + if err != nil { + t.Errorf("Failed to create route entry: %v", err) + } + + describeArgs := DescribeRouteTablesArgs{ + VRouterId: vrouterId, + } + + routeTables, _, err := client.DescribeRouteTables(&describeArgs) + + if err != nil { + t.Errorf("Failed to describe route tables: %v", err) + } else { + t.Logf("RouteTables of VRouter %s: %++v", vrouterId, routeTables) + } + + err = client.WaitForAllRouteEntriesAvailable(vrouterId, routeTableId, 60) + if err != nil { + t.Errorf("Failed to wait route entries: %v", err) + } + deleteArgs := DeleteRouteEntryArgs{ + RouteTableId: routeTableId, + DestinationCidrBlock: cidrBlock, + NextHopId: instanceId, + } + + err = client.DeleteRouteEntry(&deleteArgs) + if err != nil { + t.Errorf("Failed to delete route entry: %v", err) + } + +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/security_groups.go b/vendor/github.com/denverdino/aliyungo/ecs/security_groups.go new file mode 100644 index 0000000000..2e895dfc36 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/security_groups.go @@ -0,0 +1,208 @@ +package ecs + +import ( + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type NicType string + +const ( + NicTypeInternet = NicType("internet") + NicTypeIntranet = NicType("intranet") +) + +type IpProtocol string + +const ( + IpProtocolAll = IpProtocol("all") + IpProtocolTCP = IpProtocol("tcp") + IpProtocolUDP = IpProtocol("udp") + IpProtocolICMP = IpProtocol("icmp") + IpProtocolGRE = IpProtocol("gre") +) + +type PermissionPolicy string + +const ( + PermissionPolicyAccept = PermissionPolicy("accept") + PermissionPolicyDrop = PermissionPolicy("drop") +) + +type DescribeSecurityGroupAttributeArgs struct { + SecurityGroupId string + RegionId common.Region + NicType NicType //enum for internet (default) |intranet +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&permissiontype +type PermissionType struct { + IpProtocol IpProtocol + PortRange string + SourceCidrIp string + SourceGroupId string + SourceGroupOwnerAccount string + Policy PermissionPolicy + NicType NicType +} + +type DescribeSecurityGroupAttributeResponse struct { + common.Response + + SecurityGroupId string + SecurityGroupName string + RegionId common.Region + Description string + Permissions struct { + Permission []PermissionType + } + VpcId string +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/securitygroup&describesecuritygroupattribute +func (client *Client) DescribeSecurityGroupAttribute(args *DescribeSecurityGroupAttributeArgs) (response *DescribeSecurityGroupAttributeResponse, err error) { + response = &DescribeSecurityGroupAttributeResponse{} + err = client.Invoke("DescribeSecurityGroupAttribute", args, response) + if err != nil { + return nil, err + } + return response, nil +} + +type DescribeSecurityGroupsArgs struct { + RegionId common.Region + VpcId string + common.Pagination +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&securitygroupitemtype +type SecurityGroupItemType struct { + SecurityGroupId string + SecurityGroupName string + Description string + VpcId string + CreationTime util.ISO6801Time +} + +type DescribeSecurityGroupsResponse struct { + common.Response + common.PaginationResult + + RegionId common.Region + SecurityGroups struct { + SecurityGroup []SecurityGroupItemType + } +} + +// DescribeSecurityGroups describes security groups +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/securitygroup&describesecuritygroups +func (client *Client) DescribeSecurityGroups(args *DescribeSecurityGroupsArgs) (securityGroupItems []SecurityGroupItemType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeSecurityGroupsResponse{} + + err = client.Invoke("DescribeSecurityGroups", args, &response) + + if err != nil { + return nil, nil, err + } + + return response.SecurityGroups.SecurityGroup, &response.PaginationResult, nil +} + +type CreateSecurityGroupArgs struct { + RegionId common.Region + SecurityGroupName string + Description string + VpcId string + ClientToken string +} + +type CreateSecurityGroupResponse struct { + common.Response + + SecurityGroupId string +} + +// CreateSecurityGroup creates security group +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/securitygroup&createsecuritygroup +func (client *Client) CreateSecurityGroup(args *CreateSecurityGroupArgs) (securityGroupId string, err error) { + response := CreateSecurityGroupResponse{} + err = client.Invoke("CreateSecurityGroup", args, &response) + if err != nil { + return "", err + } + return response.SecurityGroupId, err +} + +type DeleteSecurityGroupArgs struct { + RegionId common.Region + SecurityGroupId string +} + +type DeleteSecurityGroupResponse struct { + common.Response +} + +// DeleteSecurityGroup deletes security group +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/securitygroup&deletesecuritygroup +func (client *Client) DeleteSecurityGroup(regionId common.Region, securityGroupId string) error { + args := DeleteSecurityGroupArgs{ + RegionId: regionId, + SecurityGroupId: securityGroupId, + } + response := DeleteSecurityGroupResponse{} + err := client.Invoke("DeleteSecurityGroup", &args, &response) + return err +} + +type ModifySecurityGroupAttributeArgs struct { + RegionId common.Region + SecurityGroupId string + SecurityGroupName string + Description string +} + +type ModifySecurityGroupAttributeResponse struct { + common.Response +} + +// ModifySecurityGroupAttribute modifies attribute of security group +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/securitygroup&modifysecuritygroupattribute +func (client *Client) ModifySecurityGroupAttribute(args *ModifySecurityGroupAttributeArgs) error { + response := ModifySecurityGroupAttributeResponse{} + err := client.Invoke("ModifySecurityGroupAttribute", args, &response) + return err +} + +type AuthorizeSecurityGroupArgs struct { + SecurityGroupId string + RegionId common.Region + IpProtocol IpProtocol + PortRange string + SourceGroupId string + SourceGroupOwnerAccount string + SourceCidrIp string // IPv4 only, default 0.0.0.0/0 + Policy PermissionPolicy // enum of accept (default) | drop + Priority int // 1 - 100, default 1 + NicType NicType // enum of internet | intranet (default) +} + +type AuthorizeSecurityGroupResponse struct { + common.Response +} + +// AuthorizeSecurityGroup authorize permissions to security group +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/securitygroup&authorizesecuritygroup +func (client *Client) AuthorizeSecurityGroup(args *AuthorizeSecurityGroupArgs) error { + response := AuthorizeSecurityGroupResponse{} + err := client.Invoke("AuthorizeSecurityGroup", args, &response) + return err +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/security_groups_test.go b/vendor/github.com/denverdino/aliyungo/ecs/security_groups_test.go new file mode 100644 index 0000000000..c7589e9daf --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/security_groups_test.go @@ -0,0 +1,108 @@ +package ecs + +import ( + "testing" + + "github.com/denverdino/aliyungo/common" +) + +func TestSecurityGroups(t *testing.T) { + + client := NewTestClient() + regions, err := client.DescribeRegions() + + t.Log("regions: ", regions, err) + + for _, region := range regions { + + arg := DescribeSecurityGroupsArgs{ + RegionId: region.RegionId, + } + + sgs, _, err := client.DescribeSecurityGroups(&arg) + if err != nil { + t.Errorf("Failed to DescribeSecurityGroups for region %s: %v", region.RegionId, err) + continue + } + for _, sg := range sgs { + t.Logf("SecurityGroup: %++v", sg) + + args := DescribeSecurityGroupAttributeArgs{ + SecurityGroupId: sg.SecurityGroupId, + RegionId: region.RegionId, + } + sga, err := client.DescribeSecurityGroupAttribute(&args) + if err != nil { + t.Errorf("Failed to DescribeSecurityGroupAttribute %s: %v", sg.SecurityGroupId, err) + continue + } + t.Logf("SecurityGroup Attribute: %++v", sga) + + } + } +} + +func TestECSSecurityGroupCreationAndDeletion(t *testing.T) { + client := NewTestClient() + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to describe instance attribute %s: %v", TestInstanceId, err) + } + regionId := instance.RegionId + + _testECSSecurityGroupCreationAndDeletion(t, client, regionId, "") + +} + +func _testECSSecurityGroupCreationAndDeletion(t *testing.T, client *Client, regionId common.Region, vpcId string) { + + sgName := "test-security-group" + args := CreateSecurityGroupArgs{ + RegionId: regionId, + VpcId: vpcId, + SecurityGroupName: sgName, + } + + sgId, err := client.CreateSecurityGroup(&args) + if err != nil { + t.Fatalf("Failed to create security group %s: %v", sgName, err) + } + t.Logf("Security group %s is created successfully.", sgId) + + describeArgs := DescribeSecurityGroupAttributeArgs{ + SecurityGroupId: sgId, + RegionId: regionId, + } + sg, err := client.DescribeSecurityGroupAttribute(&describeArgs) + if err != nil { + t.Errorf("Failed to describe security group %s: %v", sgId, err) + } + t.Logf("Security group %s: %++v", sgId, sg) + + newName := "test-security-group-new" + modifyArgs := ModifySecurityGroupAttributeArgs{ + SecurityGroupId: sgId, + RegionId: regionId, + SecurityGroupName: newName, + } + err = client.ModifySecurityGroupAttribute(&modifyArgs) + if err != nil { + t.Errorf("Failed to modify security group %s: %v", sgId, err) + } else { + sg, err := client.DescribeSecurityGroupAttribute(&describeArgs) + if err != nil { + t.Errorf("Failed to describe security group %s: %v", sgId, err) + } + t.Logf("Security group %s: %++v", sgId, sg) + if sg.SecurityGroupName != newName { + t.Errorf("Failed to modify security group %s with new name %s", sgId, newName) + } + } + + err = client.DeleteSecurityGroup(regionId, sgId) + + if err != nil { + t.Fatalf("Failed to delete security group %s: %v", sgId, err) + } + t.Logf("Security group %s is deleted successfully.", sgId) +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/snapshots.go b/vendor/github.com/denverdino/aliyungo/ecs/snapshots.go new file mode 100644 index 0000000000..fb6f9c8e10 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/snapshots.go @@ -0,0 +1,131 @@ +package ecs + +import ( + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type DescribeSnapshotsArgs struct { + RegionId common.Region + InstanceId string + DiskId string + SnapshotIds []string //["s-xxxxxxxxx", "s-yyyyyyyyy", ..."s-zzzzzzzzz"] + common.Pagination +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&snapshottype +type SnapshotType struct { + SnapshotId string + SnapshotName string + Description string + Progress string + SourceDiskId string + SourceDiskSize int + SourceDiskType string //enum for System | Data + ProductCode string + CreationTime util.ISO6801Time +} + +type DescribeSnapshotsResponse struct { + common.Response + common.PaginationResult + Snapshots struct { + Snapshot []SnapshotType + } +} + +// DescribeSnapshots describe snapshots +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/snapshot&describesnapshots +func (client *Client) DescribeSnapshots(args *DescribeSnapshotsArgs) (snapshots []SnapshotType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeSnapshotsResponse{} + + err = client.Invoke("DescribeSnapshots", args, &response) + + if err != nil { + return nil, nil, err + } + return response.Snapshots.Snapshot, &response.PaginationResult, nil + +} + +type DeleteSnapshotArgs struct { + SnapshotId string +} + +type DeleteSnapshotResponse struct { + common.Response +} + +// DeleteSnapshot deletes snapshot +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/snapshot&deletesnapshot +func (client *Client) DeleteSnapshot(snapshotId string) error { + args := DeleteSnapshotArgs{SnapshotId: snapshotId} + response := DeleteSnapshotResponse{} + + return client.Invoke("DeleteSnapshot", &args, &response) +} + +type CreateSnapshotArgs struct { + DiskId string + SnapshotName string + Description string + ClientToken string +} + +type CreateSnapshotResponse struct { + common.Response + SnapshotId string +} + +// CreateSnapshot creates a new snapshot +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/snapshot&createsnapshot +func (client *Client) CreateSnapshot(args *CreateSnapshotArgs) (snapshotId string, err error) { + + response := CreateSnapshotResponse{} + + err = client.Invoke("CreateSnapshot", args, &response) + if err == nil { + snapshotId = response.SnapshotId + } + return snapshotId, err +} + +// Default timeout value for WaitForSnapShotReady method +const SnapshotDefaultTimeout = 120 + +// WaitForSnapShotReady waits for snapshot ready +func (client *Client) WaitForSnapShotReady(regionId common.Region, snapshotId string, timeout int) error { + if timeout <= 0 { + timeout = SnapshotDefaultTimeout + } + for { + args := DescribeSnapshotsArgs{ + RegionId: regionId, + SnapshotIds: []string{snapshotId}, + } + + snapshots, _, err := client.DescribeSnapshots(&args) + if err != nil { + return err + } + if snapshots == nil || len(snapshots) == 0 { + return common.GetClientErrorFromString("Not found") + } + if snapshots[0].Progress == "100%" { + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + } + return nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/snapshots_test.go b/vendor/github.com/denverdino/aliyungo/ecs/snapshots_test.go new file mode 100644 index 0000000000..c85982ec05 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/snapshots_test.go @@ -0,0 +1,76 @@ +package ecs + +import ( + "testing" +) + +func TestSnapshot(t *testing.T) { + + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := DescribeSnapshotsArgs{} + + args.InstanceId = TestInstanceId + args.RegionId = instance.RegionId + snapshots, _, err := client.DescribeSnapshots(&args) + + if err != nil { + t.Errorf("Failed to DescribeSnapshots for instance %s: %v", TestInstanceId, err) + } + + for _, snapshot := range snapshots { + t.Logf("Snapshot of instance %s: %++v", TestInstanceId, snapshot) + } +} + +func TestSnapshotCreationAndDeletion(t *testing.T) { + if TestQuick { + return + } + + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + //Describe disk monitor data + diskArgs := DescribeDisksArgs{ + InstanceId: TestInstanceId, + RegionId: instance.RegionId, + } + + disks, _, err := client.DescribeDisks(&diskArgs) + if err != nil { + t.Fatalf("Failed to DescribeDisks for instance %s: %v", TestInstanceId, err) + } + + diskId := disks[0].DiskId + + args := CreateSnapshotArgs{ + DiskId: diskId, + SnapshotName: "My_Test_Snapshot", + Description: "My Test Snapshot Description", + ClientToken: client.GenerateClientToken(), + } + + snapshotId, err := client.CreateSnapshot(&args) + if err != nil { + t.Errorf("Failed to CreateSnapshot for disk %s: %v", diskId, err) + } + client.WaitForSnapShotReady(instance.RegionId, snapshotId, 0) + + err = client.DeleteSnapshot(snapshotId) + if err != nil { + t.Errorf("Failed to DeleteSnapshot for disk %s: %v", diskId, err) + } + + t.Logf("Snapshot %s is deleted successfully.", snapshotId) + +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/tags.go b/vendor/github.com/denverdino/aliyungo/ecs/tags.go new file mode 100644 index 0000000000..5ffd4931aa --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/tags.go @@ -0,0 +1,120 @@ +package ecs + +import "github.com/denverdino/aliyungo/common" + +type TagResourceType string + +const ( + TagResourceImage = TagResourceType("image") + TagResourceInstance = TagResourceType("instance") + TagResourceSnapshot = TagResourceType("snapshot") + TagResourceDisk = TagResourceType("disk") +) + +type AddTagsArgs struct { + ResourceId string + ResourceType TagResourceType //image, instance, snapshot or disk + RegionId common.Region + Tag map[string]string +} + +type AddTagsResponse struct { + common.Response +} + +// AddTags Add tags to resource +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/tags&addtags +func (client *Client) AddTags(args *AddTagsArgs) error { + response := AddTagsResponse{} + err := client.Invoke("AddTags", args, &response) + return err +} + +type RemoveTagsArgs struct { + ResourceId string + ResourceType TagResourceType //image, instance, snapshot or disk + RegionId common.Region + Tag map[string]string +} + +type RemoveTagsResponse struct { + common.Response +} + +// RemoveTags remove tags to resource +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/tags&removetags +func (client *Client) RemoveTags(args *RemoveTagsArgs) error { + response := RemoveTagsResponse{} + err := client.Invoke("RemoveTags", args, &response) + return err +} + +type ResourceItemType struct { + ResourceId string + ResourceType TagResourceType + RegionId common.Region +} + +type DescribeResourceByTagsArgs struct { + ResourceType TagResourceType //image, instance, snapshot or disk + RegionId common.Region + Tag map[string]string + common.Pagination +} + +type DescribeResourceByTagsResponse struct { + common.Response + common.PaginationResult + Resources struct { + Resource []ResourceItemType + } +} + +// DescribeResourceByTags describe resource by tags +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/tags&describeresourcebytags +func (client *Client) DescribeResourceByTags(args *DescribeResourceByTagsArgs) (resources []ResourceItemType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeResourceByTagsResponse{} + err = client.Invoke("DescribeResourceByTags", args, &response) + if err != nil { + return nil, nil, err + } + return response.Resources.Resource, &response.PaginationResult, nil +} + +type TagItemType struct { + TagKey string + TagValue string +} + +type DescribeTagsArgs struct { + RegionId common.Region + ResourceType TagResourceType //image, instance, snapshot or disk + ResourceId string + Tag map[string]string + common.Pagination +} + +type DescribeTagsResponse struct { + common.Response + common.PaginationResult + Tags struct { + Tag []TagItemType + } +} + +// DescribeResourceByTags describe resource by tags +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/tags&describeresourcebytags +func (client *Client) DescribeTags(args *DescribeTagsArgs) (tags []TagItemType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeTagsResponse{} + err = client.Invoke("DescribeTags", args, &response) + if err != nil { + return nil, nil, err + } + return response.Tags.Tag, &response.PaginationResult, nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/tags_test.go b/vendor/github.com/denverdino/aliyungo/ecs/tags_test.go new file mode 100644 index 0000000000..1b05eef9cb --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/tags_test.go @@ -0,0 +1,98 @@ +package ecs + +import ( + "testing" +) + +var TestTags = map[string]string{ + "test": "api", + "gosdk": "1.0", +} + +func TestAddTags(t *testing.T) { + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := AddTagsArgs{ + RegionId: instance.RegionId, + ResourceId: instance.InstanceId, + ResourceType: TagResourceInstance, + Tag: TestTags, + } + err = client.AddTags(&args) + + if err != nil { + t.Errorf("Failed to AddTags for instance %s: %v", TestInstanceId, err) + } + +} + +func TestDescribeResourceByTags(t *testing.T) { + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := DescribeResourceByTagsArgs{ + RegionId: instance.RegionId, + ResourceType: TagResourceInstance, + Tag: TestTags, + } + result, _, err := client.DescribeResourceByTags(&args) + + if err != nil { + t.Errorf("Failed to DescribeResourceByTags: %v", err) + } else { + t.Logf("result: %v", result) + } +} + +func TestDescribeTags(t *testing.T) { + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := DescribeTagsArgs{ + RegionId: instance.RegionId, + ResourceType: TagResourceInstance, + } + result, _, err := client.DescribeTags(&args) + + if err != nil { + t.Errorf("Failed to DescribeTags: %v", err) + } else { + t.Logf("result: %v", result) + } +} + +func TestRemoveTags(t *testing.T) { + + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to DescribeInstanceAttribute for instance %s: %v", TestInstanceId, err) + } + + args := RemoveTagsArgs{ + RegionId: instance.RegionId, + ResourceId: instance.InstanceId, + ResourceType: TagResourceInstance, + Tag: TestTags, + } + err = client.RemoveTags(&args) + + if err != nil { + t.Errorf("Failed to RemoveTags for instance %s: %v", TestInstanceId, err) + } + +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/vpcs.go b/vendor/github.com/denverdino/aliyungo/ecs/vpcs.go new file mode 100644 index 0000000000..7a62857cd1 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/vpcs.go @@ -0,0 +1,151 @@ +package ecs + +import ( + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type CreateVpcArgs struct { + RegionId common.Region + CidrBlock string //192.168.0.0/16 or 172.16.0.0/16 (default) + VpcName string + Description string + ClientToken string +} + +type CreateVpcResponse struct { + common.Response + VpcId string + VRouterId string + RouteTableId string +} + +// CreateVpc creates Virtual Private Cloud +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vpc&createvpc +func (client *Client) CreateVpc(args *CreateVpcArgs) (resp *CreateVpcResponse, err error) { + response := CreateVpcResponse{} + err = client.Invoke("CreateVpc", args, &response) + if err != nil { + return nil, err + } + return &response, err +} + +type DeleteVpcArgs struct { + VpcId string +} + +type DeleteVpcResponse struct { + common.Response +} + +// DeleteVpc deletes Virtual Private Cloud +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vpc&deletevpc +func (client *Client) DeleteVpc(vpcId string) error { + args := DeleteVpcArgs{ + VpcId: vpcId, + } + response := DeleteVpcResponse{} + return client.Invoke("DeleteVpc", &args, &response) +} + +type VpcStatus string + +const ( + VpcStatusPending = VpcStatus("Pending") + VpcStatusAvailable = VpcStatus("Available") +) + +type DescribeVpcsArgs struct { + VpcId string + RegionId common.Region + common.Pagination +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&vpcsettype +type VpcSetType struct { + VpcId string + RegionId common.Region + Status VpcStatus // enum Pending | Available + VpcName string + VSwitchIds struct { + VSwitchId []string + } + CidrBlock string + VRouterId string + Description string + CreationTime util.ISO6801Time +} + +type DescribeVpcsResponse struct { + common.Response + common.PaginationResult + Vpcs struct { + Vpc []VpcSetType + } +} + +// DescribeInstanceStatus describes instance status +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vpc&describevpcs +func (client *Client) DescribeVpcs(args *DescribeVpcsArgs) (vpcs []VpcSetType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeVpcsResponse{} + + err = client.Invoke("DescribeVpcs", args, &response) + + if err == nil { + return response.Vpcs.Vpc, &response.PaginationResult, nil + } + + return nil, nil, err +} + +type ModifyVpcAttributeArgs struct { + VpcId string + VpcName string + Description string +} + +type ModifyVpcAttributeResponse struct { + common.Response +} + +// ModifyVpcAttribute modifies attribute of Virtual Private Cloud +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vpc&modifyvpcattribute +func (client *Client) ModifyVpcAttribute(args *ModifyVpcAttributeArgs) error { + response := ModifyVpcAttributeResponse{} + return client.Invoke("ModifyVpcAttribute", args, &response) +} + +// WaitForInstance waits for instance to given status +func (client *Client) WaitForVpcAvailable(regionId common.Region, vpcId string, timeout int) error { + if timeout <= 0 { + timeout = DefaultTimeout + } + args := DescribeVpcsArgs{ + RegionId: regionId, + VpcId: vpcId, + } + for { + vpcs, _, err := client.DescribeVpcs(&args) + if err != nil { + return err + } + if len(vpcs) > 0 && vpcs[0].Status == VpcStatusAvailable { + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + } + return nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/vpcs_test.go b/vendor/github.com/denverdino/aliyungo/ecs/vpcs_test.go new file mode 100644 index 0000000000..f7e5a6a8e7 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/vpcs_test.go @@ -0,0 +1,177 @@ +package ecs + +import ( + "testing" + "time" + + "github.com/denverdino/aliyungo/common" +) + +func TestVPCCreationAndDeletion(t *testing.T) { + + client := NewTestClient() + + instance, err := client.DescribeInstanceAttribute(TestInstanceId) + if err != nil { + t.Fatalf("Failed to describe instance %s: %v", TestInstanceId, err) + } + + //client.SetDebug(true) + + regionId := instance.RegionId + zoneId := instance.ZoneId + + args := CreateVpcArgs{ + RegionId: regionId, + VpcName: "My_AliyunGO_test_VPC", + Description: "My AliyunGO test VPC", + CidrBlock: "172.16.0.0/16", + ClientToken: client.GenerateClientToken(), + } + + resp, err := client.CreateVpc(&args) + if err != nil { + t.Fatalf("Failed to create VPC: %v", err) + } + t.Logf("VPC is created successfully: %++v", resp) + + vpcId := resp.VpcId + newName := args.VpcName + "_update" + newDesc := args.Description + "_update" + modifyArgs := ModifyVpcAttributeArgs{ + VpcId: vpcId, + VpcName: newName, + Description: newDesc, + } + err = client.ModifyVpcAttribute(&modifyArgs) + if err != nil { + t.Errorf("Failed to modify VPC: %v", err) + } + + describeArgs := DescribeVpcsArgs{ + VpcId: vpcId, + RegionId: regionId, + } + vpcs, _, err := client.DescribeVpcs(&describeArgs) + if err != nil { + t.Errorf("Failed to describe VPCs: %v", err) + } + t.Logf("VPCs: %++v", vpcs) + if vpcs[0].VpcName != newName { + t.Errorf("Failed to modify VPC with new name: %s", newName) + } + + err = client.WaitForVpcAvailable(regionId, vpcId, 60) + if err != nil { + t.Errorf("Failed to wait VPC to available: %v", err) + } + + _testECSSecurityGroupCreationAndDeletion(t, client, regionId, vpcId) + + //Test VSwitch + vSwitchId, err := testCreateVSwitch(t, client, regionId, zoneId, vpcId, resp.VRouterId) + if err != nil { + t.Errorf("Failed to create VSwitch: %v", err) + } else { + if TestIAmRich { + instanceId, sgId, err := testCreateInstanceVpc(t, client, regionId, vpcId, vSwitchId, instance.ImageId) + + if err == nil { + testEipAddress(t, client, regionId, instanceId) + + //Test VRouter + testVRouter(t, client, regionId, vpcId, resp.VRouterId, instanceId) + + } + + if instanceId != "" { + err = client.StopInstance(instanceId, true) + if err != nil { + t.Errorf("Failed to stop instance %s: %v", instanceId, err) + } else { + err = client.WaitForInstance(instanceId, Stopped, 0) + if err != nil { + t.Errorf("Instance %s is failed to stop: %v", instanceId, err) + } + t.Logf("Instance %s is stopped successfully.", instanceId) + } + err = client.DeleteInstance(instanceId) + + if err != nil { + t.Errorf("Failed to delete instance %s: %v", instanceId, err) + } else { + t.Logf("Instance %s is deleted successfully.", instanceId) + } + } + if sgId != "" { + //Wait the instance deleted completedly + time.Sleep(10 * time.Second) + err = client.DeleteSecurityGroup(regionId, sgId) + if err != nil { + t.Fatalf("Failed to delete security group %s: %v", sgId, err) + } + t.Logf("Security group %s is deleted successfully.", sgId) + } + } + } + + if vSwitchId != "" { + err = client.DeleteVSwitch(vSwitchId) + if err != nil { + t.Fatalf("Failed to delete VSwitch: %v", err) + } + t.Logf("VSwitch %s is deleted successfully.", vSwitchId) + } + + time.Sleep(20 * time.Second) + + err = client.DeleteVpc(vpcId) + if err != nil { + t.Errorf("Failed to delete VPC: %v", err) + } + t.Logf("VPC %s is deleted successfully.", vpcId) + +} + +func testCreateInstanceVpc(t *testing.T, client *Client, regionId common.Region, vpcId string, vswitchId, imageId string) (instanceId string, sgId string, err error) { + sgName := "test-security-group" + args := CreateSecurityGroupArgs{ + RegionId: regionId, + VpcId: vpcId, + SecurityGroupName: sgName, + } + + sgId, err = client.CreateSecurityGroup(&args) + + if err != nil { + t.Errorf("Failed to create security group %s: %v", sgName, err) + return "", "", err + } + + createArgs := CreateInstanceArgs{ + RegionId: regionId, + ImageId: imageId, + InstanceType: "ecs.t1.small", + SecurityGroupId: sgId, + VSwitchId: vswitchId, + } + + instanceId, err = client.CreateInstance(&createArgs) + if err != nil { + t.Errorf("Failed to create instance from Image %s: %v", imageId, err) + return "", sgId, err + } + t.Logf("Instance %s is created successfully.", instanceId) + instance, err := client.DescribeInstanceAttribute(instanceId) + t.Logf("Instance: %++v %v", instance, err) + err = client.WaitForInstance(instanceId, Stopped, 0) + + err = client.StartInstance(instanceId) + if err != nil { + t.Errorf("Failed to start instance %s: %v", instanceId, err) + return instanceId, sgId, err + } + err = client.WaitForInstance(instanceId, Running, 0) + + return instanceId, sgId, err +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/vrouters.go b/vendor/github.com/denverdino/aliyungo/ecs/vrouters.go new file mode 100644 index 0000000000..059a324bd9 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/vrouters.go @@ -0,0 +1,68 @@ +package ecs + +import ( + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type DescribeVRoutersArgs struct { + VRouterId string + RegionId common.Region + common.Pagination +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&vroutersettype +type VRouterSetType struct { + VRouterId string + RegionId common.Region + VpcId string + RouteTableIds struct { + RouteTableId []string + } + VRouterName string + Description string + CreationTime util.ISO6801Time +} + +type DescribeVRoutersResponse struct { + common.Response + common.PaginationResult + VRouters struct { + VRouter []VRouterSetType + } +} + +// DescribeVRouters describes Virtual Routers +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vrouter&describevrouters +func (client *Client) DescribeVRouters(args *DescribeVRoutersArgs) (vrouters []VRouterSetType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeVRoutersResponse{} + + err = client.Invoke("DescribeVRouters", args, &response) + + if err == nil { + return response.VRouters.VRouter, &response.PaginationResult, nil + } + + return nil, nil, err +} + +type ModifyVRouterAttributeArgs struct { + VRouterId string + VRouterName string + Description string +} + +type ModifyVRouterAttributeResponse struct { + common.Response +} + +// ModifyVRouterAttribute modifies attribute of Virtual Router +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vrouter&modifyvrouterattribute +func (client *Client) ModifyVRouterAttribute(args *ModifyVRouterAttributeArgs) error { + response := ModifyVRouterAttributeResponse{} + return client.Invoke("ModifyVRouterAttribute", args, &response) +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/vrouters_test.go b/vendor/github.com/denverdino/aliyungo/ecs/vrouters_test.go new file mode 100644 index 0000000000..e8e575dc46 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/vrouters_test.go @@ -0,0 +1,40 @@ +package ecs + +import ( + "testing" + + "github.com/denverdino/aliyungo/common" +) + +func testVRouter(t *testing.T, client *Client, regionId common.Region, vpcId string, vrouterId string, instanceId string) { + + newName := "My_Aliyun_test_VRouter" + + modifyArgs := ModifyVRouterAttributeArgs{ + VRouterId: vrouterId, + VRouterName: newName, + Description: newName, + } + + err := client.ModifyVRouterAttribute(&modifyArgs) + if err != nil { + t.Errorf("Failed to modify VRouters: %v", err) + } + + args := DescribeVRoutersArgs{ + VRouterId: vrouterId, + RegionId: regionId, + } + + vrouters, _, err := client.DescribeVRouters(&args) + if err != nil { + t.Errorf("Failed to describe VRouters: %v", err) + } + t.Logf("VRouters: %++v", vrouters) + if vrouters[0].VRouterName != newName { + t.Errorf("Failed to modify VRouters with new name: %s", newName) + } + + testRouteTable(t, client, regionId, vpcId, vrouterId, vrouters[0].RouteTableIds.RouteTableId[0], instanceId) + +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/vswitches.go b/vendor/github.com/denverdino/aliyungo/ecs/vswitches.go new file mode 100644 index 0000000000..8bf10394a7 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/vswitches.go @@ -0,0 +1,152 @@ +package ecs + +import ( + "time" + + "github.com/denverdino/aliyungo/common" + "github.com/denverdino/aliyungo/util" +) + +type CreateVSwitchArgs struct { + ZoneId string + CidrBlock string + VpcId string + VSwitchName string + Description string + ClientToken string +} + +type CreateVSwitchResponse struct { + common.Response + VSwitchId string +} + +// CreateVSwitch creates Virtual Switch +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vswitch&createvswitch +func (client *Client) CreateVSwitch(args *CreateVSwitchArgs) (vswitchId string, err error) { + response := CreateVSwitchResponse{} + err = client.Invoke("CreateVSwitch", args, &response) + if err != nil { + return "", err + } + return response.VSwitchId, err +} + +type DeleteVSwitchArgs struct { + VSwitchId string +} + +type DeleteVSwitchResponse struct { + common.Response +} + +// DeleteVSwitch deletes Virtual Switch +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vswitch&deletevswitch +func (client *Client) DeleteVSwitch(VSwitchId string) error { + args := DeleteVSwitchArgs{ + VSwitchId: VSwitchId, + } + response := DeleteVSwitchResponse{} + return client.Invoke("DeleteVSwitch", &args, &response) +} + +type DescribeVSwitchesArgs struct { + VpcId string + VSwitchId string + ZoneId string + common.Pagination +} + +type VSwitchStatus string + +const ( + VSwitchStatusPending = VSwitchStatus("Pending") + VSwitchStatusAvailable = VSwitchStatus("Available") +) + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&vswitchsettype +type VSwitchSetType struct { + VSwitchId string + VpcId string + Status VSwitchStatus // enum Pending | Available + CidrBlock string + ZoneId string + AvailableIpAddressCount int + Description string + VSwitchName string + CreationTime util.ISO6801Time +} + +type DescribeVSwitchesResponse struct { + common.Response + common.PaginationResult + VSwitches struct { + VSwitch []VSwitchSetType + } +} + +// DescribeVSwitches describes Virtual Switches +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vswitch&describevswitches +func (client *Client) DescribeVSwitches(args *DescribeVSwitchesArgs) (vswitches []VSwitchSetType, pagination *common.PaginationResult, err error) { + args.Validate() + response := DescribeVSwitchesResponse{} + + err = client.Invoke("DescribeVSwitches", args, &response) + + if err == nil { + return response.VSwitches.VSwitch, &response.PaginationResult, nil + } + + return nil, nil, err +} + +type ModifyVSwitchAttributeArgs struct { + VSwitchId string + VSwitchName string + Description string +} + +type ModifyVSwitchAttributeResponse struct { + common.Response +} + +// ModifyVSwitchAttribute modifies attribute of Virtual Private Cloud +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/vswitch&modifyvswitchattribute +func (client *Client) ModifyVSwitchAttribute(args *ModifyVSwitchAttributeArgs) error { + response := ModifyVSwitchAttributeResponse{} + return client.Invoke("ModifyVSwitchAttribute", args, &response) +} + +// WaitForVSwitchAvailable waits for VSwitch to given status +func (client *Client) WaitForVSwitchAvailable(vpcId string, vswitchId string, timeout int) error { + if timeout <= 0 { + timeout = DefaultTimeout + } + args := DescribeVSwitchesArgs{ + VpcId: vpcId, + VSwitchId: vswitchId, + } + for { + vswitches, _, err := client.DescribeVSwitches(&args) + if err != nil { + return err + } + if len(vswitches) == 0 { + return common.GetClientErrorFromString("Not found") + } + if vswitches[0].Status == VSwitchStatusAvailable { + break + } + timeout = timeout - DefaultWaitForInterval + if timeout <= 0 { + return common.GetClientErrorFromString("Timeout") + } + time.Sleep(DefaultWaitForInterval * time.Second) + } + return nil +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/vswitches_test.go b/vendor/github.com/denverdino/aliyungo/ecs/vswitches_test.go new file mode 100644 index 0000000000..87f9ce7153 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/vswitches_test.go @@ -0,0 +1,63 @@ +package ecs + +import ( + "testing" + + "github.com/denverdino/aliyungo/common" +) + +func testCreateVSwitch(t *testing.T, client *Client, regionId common.Region, zoneId string, vpcId string, vrouterId string) (vSwitchId string, err error) { + + args := CreateVSwitchArgs{ + ZoneId: zoneId, + CidrBlock: "172.16.10.0/24", + VpcId: vpcId, + VSwitchName: "AliyunGo_test_vSwitch", + Description: "AliyunGo test vSwitch", + ClientToken: client.GenerateClientToken(), + } + + vSwitchId, err = client.CreateVSwitch(&args) + + if err != nil { + t.Errorf("Failed to create VSwitch: %v", err) + return "", err + } + + t.Logf("VSwitch is created successfully: %s", vSwitchId) + + err = client.WaitForVSwitchAvailable(vpcId, vSwitchId, 60) + if err != nil { + t.Errorf("Failed to wait VSwitch %s to available: %v", vSwitchId, err) + } + + newName := args.VSwitchName + "_update" + modifyArgs := ModifyVSwitchAttributeArgs{ + VSwitchId: vSwitchId, + VSwitchName: newName, + Description: newName, + } + + err = client.ModifyVSwitchAttribute(&modifyArgs) + if err != nil { + t.Errorf("Failed to modify VSwitch %s: %v", vSwitchId, err) + } + + argsDescribe := DescribeVSwitchesArgs{ + VpcId: vpcId, + VSwitchId: vSwitchId, + } + + vswitches, _, err := client.DescribeVSwitches(&argsDescribe) + if err != nil { + t.Errorf("Failed to describe VSwitch: %v", err) + } + + if vswitches[0].VSwitchName != newName { + t.Errorf("Failed to modify VSwitch with new name: %s", newName) + } + + t.Logf("VSwitch is : %++v", vswitches) + + return vSwitchId, err +} diff --git a/vendor/github.com/denverdino/aliyungo/ecs/zones.go b/vendor/github.com/denverdino/aliyungo/ecs/zones.go new file mode 100644 index 0000000000..5601a367bb --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/ecs/zones.go @@ -0,0 +1,60 @@ +package ecs + +import "github.com/denverdino/aliyungo/common" + +type ResourceType string + +const ( + ResourceTypeInstance = ResourceType("Instance") + ResourceTypeDisk = ResourceType("Disk") + ResourceTypeVSwitch = ResourceType("VSwitch") + ResourceTypeIOOptimizedInstance = ResourceType("IoOptimized") +) + +type DescribeZonesArgs struct { + RegionId common.Region +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&availableresourcecreationtype +type AvailableResourceCreationType struct { + ResourceTypes []ResourceType //enum for Instance, Disk, VSwitch +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&availablediskcategoriestype +type AvailableDiskCategoriesType struct { + DiskCategories []DiskCategory //enum for cloud, ephemeral, ephemeral_ssd +} + +// +// You can read doc at http://docs.aliyun.com/#/pub/ecs/open-api/datatype&zonetype +type ZoneType struct { + ZoneId string + LocalName string + AvailableResourceCreation AvailableResourceCreationType + AvailableDiskCategories AvailableDiskCategoriesType +} + +type DescribeZonesResponse struct { + common.Response + Zones struct { + Zone []ZoneType + } +} + +// DescribeZones describes zones +func (client *Client) DescribeZones(regionId common.Region) (zones []ZoneType, err error) { + args := DescribeZonesArgs{ + RegionId: regionId, + } + response := DescribeZonesResponse{} + + err = client.Invoke("DescribeZones", &args, &response) + + if err == nil { + return response.Zones.Zone, nil + } + + return []ZoneType{}, err +} diff --git a/vendor/github.com/denverdino/aliyungo/metadata/client.go b/vendor/github.com/denverdino/aliyungo/metadata/client.go new file mode 100644 index 0000000000..bcc7cb5708 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/metadata/client.go @@ -0,0 +1,344 @@ +package metadata + +import ( + "errors" + "fmt" + "github.com/denverdino/aliyungo/util" + "io" + "io/ioutil" + "net" + "net/http" + "net/url" + "strings" + "time" +) + +type Request struct { +} + +const ( + ENDPOINT = "http://100.100.100.200" + + META_VERSION_LATEST = "latest" + + RS_TYPE_META_DATA = "meta-data" + RS_TYPE_USER_DATA = "user-data" + + DNS_NAMESERVERS = "dns-conf/nameservers" + EIPV4 = "eipv4" + HOSTNAME = "hostname" + IMAGE_ID = "image-id" + INSTANCE_ID = "instance-id" + MAC = "mac" + NETWORK_TYPE = "network-type" + NTP_CONF_SERVERS = "ntp-conf/ntp-servers" + OWNER_ACCOUNT_ID = "owner-account-id" + PRIVATE_IPV4 = "private-ipv4" + REGION = "region-id" + SERIAL_NUMBER = "serial-number" + SOURCE_ADDRESS = "source-address" + VPC_CIDR_BLOCK = "vpc-cidr-block" + VPC_ID = "vpc-id" + VSWITCH_CIDR_BLOCK = "vswitch-cidr-block" + VSWITCH_ID = "vswitch-id" +) + +type IMetaDataClient interface { + Version(version string) IMetaDataClient + ResourceType(rtype string) IMetaDataClient + Resource(resource string) IMetaDataClient + Go() ([]string, error) + Url() (string, error) +} + +type MetaData struct { + c IMetaDataClient +} + +func NewMetaData(client *http.Client) *MetaData { + if client == nil { + client = &http.Client{} + } + return &MetaData{ + c: &MetaDataClient{client: client}, + } +} + +func (m *MetaData) HostName() (string, error) { + + hostname, err := m.c.Resource(HOSTNAME).Go() + if err != nil { + return "", err + } + return hostname[0], nil +} + +func (m *MetaData) ImageID() (string, error) { + + image, err := m.c.Resource(IMAGE_ID).Go() + if err != nil { + return "", err + } + return image[0], err +} + +func (m *MetaData) InstanceID() (string, error) { + + instanceid, err := m.c.Resource(INSTANCE_ID).Go() + if err != nil { + return "", err + } + return instanceid[0], err +} + +func (m *MetaData) Mac() (string, error) { + + mac, err := m.c.Resource(MAC).Go() + if err != nil { + return "", err + } + return mac[0], nil +} + +func (m *MetaData) NetworkType() (string, error) { + + network, err := m.c.Resource(NETWORK_TYPE).Go() + if err != nil { + return "", err + } + return network[0], nil +} + +func (m *MetaData) OwnerAccountID() (string, error) { + + owner, err := m.c.Resource(OWNER_ACCOUNT_ID).Go() + if err != nil { + return "", err + } + return owner[0], nil +} + +func (m *MetaData) PrivateIPv4() (string, error) { + + private, err := m.c.Resource(PRIVATE_IPV4).Go() + if err != nil { + return "", err + } + return private[0], nil +} + +func (m *MetaData) Region() (string, error) { + + region, err := m.c.Resource(REGION).Go() + if err != nil { + return "", err + } + return region[0], nil +} + +func (m *MetaData) SerialNumber() (string, error) { + + serial, err := m.c.Resource(SERIAL_NUMBER).Go() + if err != nil { + return "", err + } + return serial[0], nil +} + +func (m *MetaData) SourceAddress() (string, error) { + + source, err := m.c.Resource(SOURCE_ADDRESS).Go() + if err != nil { + return "", err + } + return source[0], nil + +} + +func (m *MetaData) VpcCIDRBlock() (string, error) { + + vpcCIDR, err := m.c.Resource(VPC_CIDR_BLOCK).Go() + if err != nil { + return "", err + } + return vpcCIDR[0], err +} + +func (m *MetaData) VpcID() (string, error) { + + vpcId, err := m.c.Resource(VPC_ID).Go() + if err != nil { + return "", err + } + return vpcId[0], err +} + +func (m *MetaData) VswitchCIDRBlock() (string, error) { + + cidr, err := m.c.Resource(VSWITCH_CIDR_BLOCK).Go() + if err != nil { + return "", err + } + return cidr[0], err +} + +func (m *MetaData) VswitchID() (string, error) { + + vswithcid, err := m.c.Resource(VSWITCH_ID).Go() + if err != nil { + return "", err + } + return vswithcid[0], err +} + +func (m *MetaData) EIPv4() (string, error) { + + eip, err := m.c.Resource(EIPV4).Go() + if err != nil { + return "", err + } + return eip[0], nil +} + +func (m *MetaData) DNSNameServers() ([]string, error) { + + data, err := m.c.Resource(DNS_NAMESERVERS).Go() + if err != nil { + return []string{}, err + } + return data, nil +} + +func (m *MetaData) NTPConfigServers() ([]string, error) { + + data, err := m.c.Resource(NTP_CONF_SERVERS).Go() + if err != nil { + return []string{}, err + } + return data, nil +} + +// +type MetaDataClient struct { + version string + resourceType string + resource string + client *http.Client +} + +func (vpc *MetaDataClient) Version(version string) IMetaDataClient { + vpc.version = version + return vpc +} + +func (vpc *MetaDataClient) ResourceType(rtype string) IMetaDataClient { + vpc.resourceType = rtype + return vpc +} + +func (vpc *MetaDataClient) Resource(resource string) IMetaDataClient { + vpc.resource = resource + return vpc +} + +var retry = util.AttemptStrategy{ + Min: 5, + Total: 5 * time.Second, + Delay: 200 * time.Millisecond, +} + +func (vpc *MetaDataClient) Url() (string, error) { + if vpc.version == "" { + vpc.version = "latest" + } + if vpc.resourceType == "" { + vpc.resourceType = "meta-data" + } + if vpc.resource == "" { + return "", errors.New("the resource you want to visit must not be nil!") + } + return fmt.Sprintf("%s/%s/%s/%s", ENDPOINT, vpc.version, vpc.resourceType, vpc.resource), nil +} + +func (vpc *MetaDataClient) Go() (resu []string, err error) { + for r := retry.Start(); r.Next(); { + resu, err = vpc.send() + if !shouldRetry(err) { + break + } + } + return resu, err +} + +func (vpc *MetaDataClient) send() ([]string, error) { + url, err := vpc.Url() + if err != nil { + return []string{}, err + } + requ, err := http.NewRequest(http.MethodGet, url, nil) + + if err != nil { + return []string{}, err + } + resp, err := vpc.client.Do(requ) + if err != nil { + return nil, err + } + if resp.StatusCode != 200 { + return nil, err + } + defer resp.Body.Close() + + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return []string{}, err + } + if string(data) == "" { + return []string{""}, nil + } + return strings.Split(string(data), "\n"), nil +} + +type TimeoutError interface { + error + Timeout() bool // Is the error a timeout? +} + +func shouldRetry(err error) bool { + if err == nil { + return false + } + + _, ok := err.(TimeoutError) + if ok { + return true + } + + switch err { + case io.ErrUnexpectedEOF, io.EOF: + return true + } + switch e := err.(type) { + case *net.DNSError: + return true + case *net.OpError: + switch e.Op { + case "read", "write": + return true + } + case *url.Error: + // url.Error can be returned either by net/url if a URL cannot be + // parsed, or by net/http if the response is closed before the headers + // are received or parsed correctly. In that later case, e.Op is set to + // the HTTP method name with the first letter uppercased. We don't want + // to retry on POST operations, since those are not idempotent, all the + // other ones should be safe to retry. + switch e.Op { + case "Get", "Put", "Delete", "Head": + return shouldRetry(e.Err) + default: + return false + } + } + return false +} diff --git a/vendor/github.com/denverdino/aliyungo/metadata/client_test.go b/vendor/github.com/denverdino/aliyungo/metadata/client_test.go new file mode 100644 index 0000000000..90eb5ccbcf --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/metadata/client_test.go @@ -0,0 +1,307 @@ +package metadata + +import ( + "errors" + "fmt" + "net/http" + "strings" + "testing" +) + +func init() { + fmt.Println("make sure your ecs is in vpc before you run ```go test```") +} + +type MockMetaDataClient struct { + I IMetaDataClient +} + +func (vpc *MockMetaDataClient) Version(version string) IMetaDataClient { + vpc.I.Version(version) + return vpc +} + +func (vpc *MockMetaDataClient) ResourceType(rtype string) IMetaDataClient { + vpc.I.ResourceType(rtype) + return vpc +} + +func (vpc *MockMetaDataClient) Resource(resource string) IMetaDataClient { + vpc.I.Resource(resource) + return vpc +} + +func (vpc *MockMetaDataClient) Url() (string, error) { + return vpc.I.Url() +} + +func (m *MockMetaDataClient) Go() ([]string, error) { + uri, err := m.Url() + if err != nil { + return []string{}, errors.New("error retrieve url") + } + if strings.Contains(uri, HOSTNAME) { + return []string{"hostname-test"}, nil + } + + if strings.Contains(uri, DNS_NAMESERVERS) { + return []string{"8.8.8.8", "8.8.4.4"}, nil + } + + if strings.Contains(uri, EIPV4) { + return []string{"1.1.1.1-test"}, nil + } + + if strings.Contains(uri, IMAGE_ID) { + return []string{"image-id-test"}, nil + } + + if strings.Contains(uri, INSTANCE_ID) { + return []string{"instanceid-test"}, nil + } + + if strings.Contains(uri, MAC) { + return []string{"mac-test"}, nil + } + + if strings.Contains(uri, NETWORK_TYPE) { + return []string{"network-type-test"}, nil + } + + if strings.Contains(uri, OWNER_ACCOUNT_ID) { + return []string{"owner-account-id-test"}, nil + } + + if strings.Contains(uri, PRIVATE_IPV4) { + return []string{"private-ipv4-test"}, nil + } + + if strings.Contains(uri, REGION) { + return []string{"region-test"}, nil + } + + if strings.Contains(uri, SERIAL_NUMBER) { + return []string{"serial-number-test"}, nil + } + + if strings.Contains(uri, SOURCE_ADDRESS) { + return []string{"source-address-test"}, nil + } + + if strings.Contains(uri, VPC_CIDR_BLOCK) { + return []string{"vpc-cidr-block-test"}, nil + } + + if strings.Contains(uri, VPC_ID) { + return []string{"vpc-id-test"}, nil + } + + if strings.Contains(uri, VSWITCH_CIDR_BLOCK) { + return []string{"vswitch-cidr-block-test"}, nil + } + + if strings.Contains(uri, VSWITCH_ID) { + return []string{"vswitch-id-test"}, nil + } + + if strings.Contains(uri, NTP_CONF_SERVERS) { + return []string{"ntp1.server.com", "ntp2.server.com"}, nil + } + + return nil, errors.New("unknow resource error.") +} + +func TestOK(t *testing.T) { + fmt.Println("ok") +} + +func NewMockMetaData(client *http.Client) *MetaData { + if client == nil { + client = &http.Client{} + } + return &MetaData{ + c: &MetaDataClient{client: client}, + } +} + +//func NewMockMetaData(client *http.Client)* MetaData{ +// if client == nil { +// client = &http.Client{} +// } +// return &MetaData{ +// c: &MockMetaDataClient{&MetaDataClient{client:client}}, +// } +//} + +func TestHostname(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.HostName() + if err != nil { + t.Errorf("hostname err: %s", err.Error()) + } + if host != "hostname-test" { + t.Error("hostname not equal hostname-test") + } +} + +func TestEIPV4(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.EIPv4() + if err != nil { + t.Errorf("EIPV4 err: %s", err.Error()) + } + if host != "1.1.1.1-test" { + t.Error("EIPV4 not equal eipv4-test") + } +} +func TestImageID(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.ImageID() + if err != nil { + t.Errorf("IMAGE_ID err: %s", err.Error()) + } + if host != "image-id-test" { + t.Error("IMAGE_ID not equal image-id-test") + } +} +func TestInstanceID(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.InstanceID() + if err != nil { + t.Errorf("IMAGE_ID err: %s", err.Error()) + } + if host != "instanceid-test" { + t.Error("IMAGE_ID not equal instanceid-test") + } +} +func TestMac(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.Mac() + if err != nil { + t.Errorf("Mac err: %s", err.Error()) + } + if host != "mac-test" { + t.Error("Mac not equal mac-test") + } +} +func TestNetworkType(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.NetworkType() + if err != nil { + t.Errorf("NetworkType err: %s", err.Error()) + } + if host != "network-type-test" { + t.Error("networktype not equal network-type-test") + } +} +func TestOwnerAccountID(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.OwnerAccountID() + if err != nil { + t.Errorf("owneraccountid err: %s", err.Error()) + } + if host != "owner-account-id-test" { + t.Error("owner-account-id not equal owner-account-id-test") + } +} +func TestPrivateIPv4(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.PrivateIPv4() + if err != nil { + t.Errorf("privateIPv4 err: %s", err.Error()) + } + if host != "private-ipv4-test" { + t.Error("privateIPv4 not equal private-ipv4-test") + } +} +func TestRegion(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.Region() + if err != nil { + t.Errorf("region err: %s", err.Error()) + } + if host != "region-test" { + t.Error("region not equal region-test") + } +} +func TestSerialNumber(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.SerialNumber() + if err != nil { + t.Errorf("serial number err: %s", err.Error()) + } + if host != "serial-number-test" { + t.Error("serial number not equal serial-number-test") + } +} + +func TestSourceAddress(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.SourceAddress() + if err != nil { + t.Errorf("source address err: %s", err.Error()) + } + if host != "source-address-test" { + t.Error("source address not equal source-address-test") + } +} +func TestVpcCIDRBlock(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.VpcCIDRBlock() + if err != nil { + t.Errorf("vpcCIDRBlock err: %s", err.Error()) + } + if host != "vpc-cidr-block-test" { + t.Error("vpc-cidr-block not equal vpc-cidr-block-test") + } +} +func TestVpcID(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.VpcID() + if err != nil { + t.Errorf("vpcID err: %s", err.Error()) + } + if host != "vpc-id-test" { + t.Error("vpc-id not equal vpc-id-test") + } +} +func TestVswitchCIDRBlock(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.VswitchCIDRBlock() + if err != nil { + t.Errorf("vswitchCIDRBlock err: %s", err.Error()) + } + if host != "vswitch-cidr-block-test" { + t.Error("vswitch-cidr-block not equal vswitch-cidr-block-test") + } +} +func TestVswitchID(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.VswitchID() + if err != nil { + t.Errorf("vswitch id err: %s", err.Error()) + } + if host != "vswitch-id-test" { + t.Error("vswitch-id not equal vswitch-id-test") + } +} +func TestNTPConfigServers(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.NTPConfigServers() + if err != nil { + t.Errorf("ntpconfigservers err: %s", err.Error()) + } + if host[0] != "ntp1.server.com" || host[1] != "ntp2.server.com" { + t.Error("ntp1.server.com not equal ntp1.server.com") + } +} +func TestDNSServers(t *testing.T) { + meta := NewMockMetaData(nil) + host, err := meta.DNSNameServers() + if err != nil { + t.Errorf("dnsservers err: %s", err.Error()) + } + if host[0] != "8.8.8.8" || host[1] != "8.8.4.4" { + t.Error("dns servers not equal 8.8.8.8/8.8.4.4") + } +} diff --git a/vendor/github.com/denverdino/aliyungo/util/attempt.go b/vendor/github.com/denverdino/aliyungo/util/attempt.go new file mode 100644 index 0000000000..2d07f03a83 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/attempt.go @@ -0,0 +1,76 @@ +package util + +import ( + "time" +) + +// AttemptStrategy is reused from the goamz package + +// AttemptStrategy represents a strategy for waiting for an action +// to complete successfully. This is an internal type used by the +// implementation of other packages. +type AttemptStrategy struct { + Total time.Duration // total duration of attempt. + Delay time.Duration // interval between each try in the burst. + Min int // minimum number of retries; overrides Total +} + +type Attempt struct { + strategy AttemptStrategy + last time.Time + end time.Time + force bool + count int +} + +// Start begins a new sequence of attempts for the given strategy. +func (s AttemptStrategy) Start() *Attempt { + now := time.Now() + return &Attempt{ + strategy: s, + last: now, + end: now.Add(s.Total), + force: true, + } +} + +// Next waits until it is time to perform the next attempt or returns +// false if it is time to stop trying. +func (a *Attempt) Next() bool { + now := time.Now() + sleep := a.nextSleep(now) + if !a.force && !now.Add(sleep).Before(a.end) && a.strategy.Min <= a.count { + return false + } + a.force = false + if sleep > 0 && a.count > 0 { + time.Sleep(sleep) + now = time.Now() + } + a.count++ + a.last = now + return true +} + +func (a *Attempt) nextSleep(now time.Time) time.Duration { + sleep := a.strategy.Delay - now.Sub(a.last) + if sleep < 0 { + return 0 + } + return sleep +} + +// HasNext returns whether another attempt will be made if the current +// one fails. If it returns true, the following call to Next is +// guaranteed to return true. +func (a *Attempt) HasNext() bool { + if a.force || a.strategy.Min > a.count { + return true + } + now := time.Now() + if now.Add(a.nextSleep(now)).Before(a.end) { + a.force = true + return true + } + return false +} diff --git a/vendor/github.com/denverdino/aliyungo/util/attempt_test.go b/vendor/github.com/denverdino/aliyungo/util/attempt_test.go new file mode 100644 index 0000000000..50e9be7a55 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/attempt_test.go @@ -0,0 +1,90 @@ +package util + +import ( + "testing" + "time" +) + +func TestAttemptTiming(t *testing.T) { + testAttempt := AttemptStrategy{ + Total: 0.25e9, + Delay: 0.1e9, + } + want := []time.Duration{0, 0.1e9, 0.2e9, 0.2e9} + got := make([]time.Duration, 0, len(want)) // avoid allocation when testing timing + t0 := time.Now() + for a := testAttempt.Start(); a.Next(); { + got = append(got, time.Now().Sub(t0)) + } + got = append(got, time.Now().Sub(t0)) + if len(got) != len(want) { + t.Fatalf("Failed!") + } + const margin = 0.01e9 + for i, got := range want { + lo := want[i] - margin + hi := want[i] + margin + if got < lo || got > hi { + t.Errorf("attempt %d want %g got %g", i, want[i].Seconds(), got.Seconds()) + } + } +} + +func TestAttemptNextHasNext(t *testing.T) { + a := AttemptStrategy{}.Start() + if !a.Next() { + t.Fatalf("Failed!") + } + if a.Next() { + t.Fatalf("Failed!") + } + + a = AttemptStrategy{}.Start() + if !a.Next() { + t.Fatalf("Failed!") + } + if a.HasNext() { + t.Fatalf("Failed!") + } + if a.Next() { + t.Fatalf("Failed!") + } + a = AttemptStrategy{Total: 2e8}.Start() + + if !a.Next() { + t.Fatalf("Failed!") + } + if !a.HasNext() { + t.Fatalf("Failed!") + } + time.Sleep(2e8) + + if !a.HasNext() { + t.Fatalf("Failed!") + } + if !a.Next() { + t.Fatalf("Failed!") + } + if a.Next() { + t.Fatalf("Failed!") + } + + a = AttemptStrategy{Total: 1e8, Min: 2}.Start() + time.Sleep(1e8) + + if !a.Next() { + t.Fatalf("Failed!") + } + if !a.HasNext() { + t.Fatalf("Failed!") + } + if !a.Next() { + t.Fatalf("Failed!") + } + if a.HasNext() { + t.Fatalf("Failed!") + } + if a.Next() { + t.Fatalf("Failed!") + } +} diff --git a/vendor/github.com/denverdino/aliyungo/util/encoding.go b/vendor/github.com/denverdino/aliyungo/util/encoding.go new file mode 100644 index 0000000000..e545e069d4 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/encoding.go @@ -0,0 +1,152 @@ +package util + +import ( + "encoding/json" + "fmt" + "log" + "net/url" + "reflect" + "strconv" + "time" +) + +//ConvertToQueryValues converts the struct to url.Values +func ConvertToQueryValues(ifc interface{}) url.Values { + values := url.Values{} + SetQueryValues(ifc, &values) + return values +} + +//SetQueryValues sets the struct to existing url.Values following ECS encoding rules +func SetQueryValues(ifc interface{}, values *url.Values) { + setQueryValues(ifc, values, "") +} + +func setQueryValues(i interface{}, values *url.Values, prefix string) { + // add to support url.Values + mapValues, ok := i.(url.Values) + if ok { + for k, _ := range mapValues { + values.Set(k, mapValues.Get(k)) + } + return + } + + elem := reflect.ValueOf(i) + if elem.Kind() == reflect.Ptr { + elem = elem.Elem() + } + elemType := elem.Type() + for i := 0; i < elem.NumField(); i++ { + + fieldName := elemType.Field(i).Name + anonymous := elemType.Field(i).Anonymous + field := elem.Field(i) + // TODO Use Tag for validation + // tag := typ.Field(i).Tag.Get("tagname") + kind := field.Kind() + if (kind == reflect.Ptr || kind == reflect.Array || kind == reflect.Slice || kind == reflect.Map || kind == reflect.Chan) && field.IsNil() { + continue + } + if kind == reflect.Ptr { + field = field.Elem() + kind = field.Kind() + } + var value string + //switch field.Interface().(type) { + switch kind { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + i := field.Int() + if i != 0 { + value = strconv.FormatInt(i, 10) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + i := field.Uint() + if i != 0 { + value = strconv.FormatUint(i, 10) + } + case reflect.Float32: + value = strconv.FormatFloat(field.Float(), 'f', 4, 32) + case reflect.Float64: + value = strconv.FormatFloat(field.Float(), 'f', 4, 64) + case reflect.Bool: + value = strconv.FormatBool(field.Bool()) + case reflect.String: + value = field.String() + case reflect.Map: + ifc := field.Interface() + m := ifc.(map[string]string) + if m != nil { + j := 0 + for k, v := range m { + j++ + keyName := fmt.Sprintf("%s.%d.Key", fieldName, j) + values.Set(keyName, k) + valueName := fmt.Sprintf("%s.%d.Value", fieldName, j) + values.Set(valueName, v) + } + } + case reflect.Slice: + switch field.Type().Elem().Kind() { + case reflect.Uint8: + value = string(field.Bytes()) + case reflect.String: + l := field.Len() + if l > 0 { + strArray := make([]string, l) + for i := 0; i < l; i++ { + strArray[i] = field.Index(i).String() + } + bytes, err := json.Marshal(strArray) + if err == nil { + value = string(bytes) + } else { + log.Printf("Failed to convert JSON: %v", err) + } + } + default: + l := field.Len() + for j := 0; j < l; j++ { + prefixName := fmt.Sprintf("%s.%d.", fieldName, (j + 1)) + ifc := field.Index(j).Interface() + //log.Printf("%s : %v", prefixName, ifc) + if ifc != nil { + setQueryValues(ifc, values, prefixName) + } + } + continue + } + + default: + switch field.Interface().(type) { + case ISO6801Time: + t := field.Interface().(ISO6801Time) + value = t.String() + case time.Time: + t := field.Interface().(time.Time) + value = GetISO8601TimeStamp(t) + default: + ifc := field.Interface() + if ifc != nil { + if anonymous { + SetQueryValues(ifc, values) + } else { + prefixName := fieldName + "." + setQueryValues(ifc, values, prefixName) + } + continue + } + } + } + if value != "" { + name := elemType.Field(i).Tag.Get("ArgName") + if name == "" { + name = fieldName + } + if prefix != "" { + name = prefix + name + } + values.Set(name, value) + } + } +} diff --git a/vendor/github.com/denverdino/aliyungo/util/encoding_test.go b/vendor/github.com/denverdino/aliyungo/util/encoding_test.go new file mode 100644 index 0000000000..dd08774105 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/encoding_test.go @@ -0,0 +1,81 @@ +package util + +import ( + "testing" + "time" +) + +type TestString string + +type SubStruct struct { + A string + B int +} + +type MyStruct struct { + SubStruct +} + +type YourStruct struct { + SubStruct SubStruct +} + +func TestConvertToQueryValues2(t *testing.T) { + + result := ConvertToQueryValues(MyStruct{SubStruct: SubStruct{A: "A", B: 1}}).Encode() + const expectedResult = "A=A&B=1" + if result != expectedResult { + // Sometimes result is not matched for the different orders + t.Logf("Incorrect encoding: %s", result) + } + result2 := ConvertToQueryValues(YourStruct{SubStruct: SubStruct{A: "A2", B: 2}}).Encode() + const expectedResult2 = "SubStruct.A=A2&SubStruct.B=2" + if result2 != expectedResult2 { + // Sometimes result is not matched for the different orders + t.Logf("Incorrect encoding: %s", result2) + } +} + +type TestStruct struct { + Format string + Version string + AccessKeyId string + Timestamp time.Time + Empty string + IntValue int `ArgName:"int-value"` + BoolPtr *bool `ArgName:"bool-ptr"` + IntPtr *int `ArgName:"int-ptr"` + StringArray []string `ArgName:"str-array"` + StructArray []SubStruct + SubStruct SubStruct + test TestString + tests []TestString + Tag map[string]string +} + +func TestConvertToQueryValues(t *testing.T) { + boolValue := true + request := TestStruct{ + Format: "JSON", + Version: "1.0", + Timestamp: time.Date(2015, time.Month(5), 26, 1, 2, 3, 4, time.UTC), + IntValue: 10, + BoolPtr: &boolValue, + StringArray: []string{"abc", "xyz"}, + StructArray: []SubStruct{ + SubStruct{A: "a", B: 1}, + SubStruct{A: "x", B: 2}, + }, + SubStruct: SubStruct{A: "M", B: 0}, + test: TestString("test"), + tests: []TestString{TestString("test1"), TestString("test2")}, + Tag: map[string]string{"abc": "xyz", "123": "456"}, + } + result := ConvertToQueryValues(&request).Encode() + const expectedResult = "Format=JSON&StructArray.1.A=a&StructArray.1.B=1&StructArray.2.A=x&StructArray.2.B=2&SubStruct.A=M&Tag.1.Key=abc&Tag.1.Value=xyz&Tag.2.Key=123&Tag.2.Value=456&Timestamp=2015-05-26T01%3A02%3A03Z&Version=1.0&bool-ptr=true&int-value=10&str-array=%5B%22abc%22%2C%22xyz%22%5D&test=test&tests=%5B%22test1%22%2C%22test2%22%5D" + if result != expectedResult { + // Sometimes result is not matched for the different orders + t.Logf("Incorrect encoding: %s", result) + } + +} diff --git a/vendor/github.com/denverdino/aliyungo/util/iso6801.go b/vendor/github.com/denverdino/aliyungo/util/iso6801.go new file mode 100644 index 0000000000..9c25e8f688 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/iso6801.go @@ -0,0 +1,80 @@ +package util + +import ( + "fmt" + "strconv" + "time" +) + +// GetISO8601TimeStamp gets timestamp string in ISO8601 format +func GetISO8601TimeStamp(ts time.Time) string { + t := ts.UTC() + return fmt.Sprintf("%04d-%02d-%02dT%02d:%02d:%02dZ", t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second()) +} + +const formatISO8601 = "2006-01-02T15:04:05Z" +const jsonFormatISO8601 = `"` + formatISO8601 + `"` +const formatISO8601withoutSeconds = "2006-01-02T15:04Z" +const jsonFormatISO8601withoutSeconds = `"` + formatISO8601withoutSeconds + `"` + +// A ISO6801Time represents a time in ISO8601 format +type ISO6801Time time.Time + +// New constructs a new iso8601.Time instance from an existing +// time.Time instance. This causes the nanosecond field to be set to +// 0, and its time zone set to a fixed zone with no offset from UTC +// (but it is *not* UTC itself). +func NewISO6801Time(t time.Time) ISO6801Time { + return ISO6801Time(time.Date( + t.Year(), + t.Month(), + t.Day(), + t.Hour(), + t.Minute(), + t.Second(), + 0, + time.UTC, + )) +} + +// IsDefault checks if the time is default +func (it *ISO6801Time) IsDefault() bool { + return *it == ISO6801Time{} +} + +// MarshalJSON serializes the ISO6801Time into JSON string +func (it ISO6801Time) MarshalJSON() ([]byte, error) { + return []byte(time.Time(it).Format(jsonFormatISO8601)), nil +} + +// UnmarshalJSON deserializes the ISO6801Time from JSON string +func (it *ISO6801Time) UnmarshalJSON(data []byte) error { + str := string(data) + + if str == "\"\"" || len(data) == 0 { + return nil + } + var t time.Time + var err error + if str[0] == '"' { + t, err = time.ParseInLocation(jsonFormatISO8601, str, time.UTC) + if err != nil { + t, err = time.ParseInLocation(jsonFormatISO8601withoutSeconds, str, time.UTC) + } + } else { + var i int64 + i, err = strconv.ParseInt(str, 10, 64) + if err == nil { + t = time.Unix(i/1000, i%1000) + } + } + if err == nil { + *it = ISO6801Time(t) + } + return err +} + +// String returns the time in ISO6801Time format +func (it ISO6801Time) String() string { + return time.Time(it).Format(formatISO8601) +} diff --git a/vendor/github.com/denverdino/aliyungo/util/iso6801_test.go b/vendor/github.com/denverdino/aliyungo/util/iso6801_test.go new file mode 100644 index 0000000000..7d6a1d4964 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/iso6801_test.go @@ -0,0 +1,91 @@ +package util + +import ( + "encoding/json" + "testing" + "time" +) + +func TestISO8601Time(t *testing.T) { + now := NewISO6801Time(time.Now().UTC()) + + data, err := json.Marshal(now) + if err != nil { + t.Fatal(err) + } + + _, err = time.Parse(`"`+formatISO8601+`"`, string(data)) + if err != nil { + t.Fatal(err) + } + + var now2 ISO6801Time + err = json.Unmarshal(data, &now2) + if err != nil { + t.Fatal(err) + } + + if now != now2 { + t.Errorf("Time %s does not equal expected %s", now2, now) + } + + if now.String() != now2.String() { + t.Fatalf("String format for %s does not equal expected %s", now2, now) + } + + type TestTimeStruct struct { + A int + B *ISO6801Time + } + var testValue TestTimeStruct + err = json.Unmarshal([]byte("{\"A\": 1, \"B\":\"\"}"), &testValue) + if err != nil { + t.Fatal(err) + } + t.Logf("%v", testValue) + if !testValue.B.IsDefault() { + t.Fatal("Invaid Unmarshal result for ISO6801Time from empty value") + } + t.Logf("ISO6801Time String(): %s", now2.String()) +} + +func TestISO8601TimeWithoutSeconds(t *testing.T) { + + const dateStr = "\"2015-10-02T12:36Z\"" + + var date ISO6801Time + + err := json.Unmarshal([]byte(dateStr), &date) + if err != nil { + t.Fatal(err) + } + + const dateStr2 = "\"2015-10-02T12:36:00Z\"" + + var date2 ISO6801Time + + err = json.Unmarshal([]byte(dateStr2), &date2) + if err != nil { + t.Fatal(err) + } + + if date != date2 { + t.Error("The two dates shoudl be equal.") + } + +} + +func TestISO8601TimeInt(t *testing.T) { + + const dateStr = "1405544146000" + + var date ISO6801Time + + err := json.Unmarshal([]byte(dateStr), &date) + if err != nil { + t.Fatal(err) + } + + t.Logf("date: %s", date) + +} diff --git a/vendor/github.com/denverdino/aliyungo/util/signature.go b/vendor/github.com/denverdino/aliyungo/util/signature.go new file mode 100644 index 0000000000..a00b27c19b --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/signature.go @@ -0,0 +1,40 @@ +package util + +import ( + "crypto/hmac" + "crypto/sha1" + "encoding/base64" + "net/url" + "strings" +) + +//CreateSignature creates signature for string following Aliyun rules +func CreateSignature(stringToSignature, accessKeySecret string) string { + // Crypto by HMAC-SHA1 + hmacSha1 := hmac.New(sha1.New, []byte(accessKeySecret)) + hmacSha1.Write([]byte(stringToSignature)) + sign := hmacSha1.Sum(nil) + + // Encode to Base64 + base64Sign := base64.StdEncoding.EncodeToString(sign) + + return base64Sign +} + +func percentReplace(str string) string { + str = strings.Replace(str, "+", "%20", -1) + str = strings.Replace(str, "*", "%2A", -1) + str = strings.Replace(str, "%7E", "~", -1) + + return str +} + +// CreateSignatureForRequest creates signature for query string values +func CreateSignatureForRequest(method string, values *url.Values, accessKeySecret string) string { + + canonicalizedQueryString := percentReplace(values.Encode()) + + stringToSign := method + "&%2F&" + url.QueryEscape(canonicalizedQueryString) + + return CreateSignature(stringToSign, accessKeySecret) +} diff --git a/vendor/github.com/denverdino/aliyungo/util/signature_test.go b/vendor/github.com/denverdino/aliyungo/util/signature_test.go new file mode 100644 index 0000000000..e5c22ccacb --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/signature_test.go @@ -0,0 +1,14 @@ +package util + +import ( + "testing" +) + +func TestCreateSignature(t *testing.T) { + + str := "GET&%2F&AccessKeyId%3Dtestid%26Action%3DDescribeRegions%26Format%3DXML%26RegionId%3Dregion1%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3DNwDAxvLU6tFE0DVb%26SignatureVersion%3D1.0%26TimeStamp%3D2012-12-26T10%253A33%253A56Z%26Version%3D2014-05-26" + + signature := CreateSignature(str, "testsecret") + + t.Log(signature) +} diff --git a/vendor/github.com/denverdino/aliyungo/util/util.go b/vendor/github.com/denverdino/aliyungo/util/util.go new file mode 100644 index 0000000000..dd68214e3b --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/util.go @@ -0,0 +1,147 @@ +package util + +import ( + "bytes" + srand "crypto/rand" + "encoding/binary" + "math/rand" + "net/http" + "net/url" + "sort" + "time" +) + +const dictionary = "_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + +//CreateRandomString create random string +func CreateRandomString() string { + b := make([]byte, 32) + l := len(dictionary) + + _, err := srand.Read(b) + + if err != nil { + // fail back to insecure rand + rand.Seed(time.Now().UnixNano()) + for i := range b { + b[i] = dictionary[rand.Int()%l] + } + } else { + for i, v := range b { + b[i] = dictionary[v%byte(l)] + } + } + + return string(b) +} + +// Encode encodes the values into ``URL encoded'' form +// ("acl&bar=baz&foo=quux") sorted by key. +func Encode(v url.Values) string { + if v == nil { + return "" + } + var buf bytes.Buffer + keys := make([]string, 0, len(v)) + for k := range v { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + vs := v[k] + prefix := url.QueryEscape(k) + for _, v := range vs { + if buf.Len() > 0 { + buf.WriteByte('&') + } + buf.WriteString(prefix) + if v != "" { + buf.WriteString("=") + buf.WriteString(url.QueryEscape(v)) + } + } + } + return buf.String() +} + +func GetGMTime() string { + return time.Now().UTC().Format(http.TimeFormat) +} + +// + +func randUint32() uint32 { + return randUint32Slice(1)[0] +} + +func randUint32Slice(c int) []uint32 { + b := make([]byte, c*4) + + _, err := srand.Read(b) + + if err != nil { + // fail back to insecure rand + rand.Seed(time.Now().UnixNano()) + for i := range b { + b[i] = byte(rand.Int()) + } + } + + n := make([]uint32, c) + + for i := range n { + n[i] = binary.BigEndian.Uint32(b[i*4 : i*4+4]) + } + + return n +} + +func toByte(n uint32, st, ed byte) byte { + return byte(n%uint32(ed-st+1) + uint32(st)) +} + +func toDigit(n uint32) byte { + return toByte(n, '0', '9') +} + +func toLowerLetter(n uint32) byte { + return toByte(n, 'a', 'z') +} + +func toUpperLetter(n uint32) byte { + return toByte(n, 'A', 'Z') +} + +type convFunc func(uint32) byte + +var convFuncs = []convFunc{toDigit, toLowerLetter, toUpperLetter} + +// tools for generating a random ECS instance password +// from 8 to 30 char MUST contain digit upper, case letter and upper case letter +// http://docs.aliyun.com/#/pub/ecs/open-api/instance&createinstance +func GenerateRandomECSPassword() string { + + // [8, 30] + l := int(randUint32()%23 + 8) + + n := randUint32Slice(l) + + b := make([]byte, l) + + b[0] = toDigit(n[0]) + b[1] = toLowerLetter(n[1]) + b[2] = toUpperLetter(n[2]) + + for i := 3; i < l; i++ { + b[i] = convFuncs[n[i]%3](n[i]) + } + + s := make([]byte, l) + perm := rand.Perm(l) + for i, v := range perm { + s[v] = b[i] + } + + return string(s) + +} diff --git a/vendor/github.com/denverdino/aliyungo/util/util_test.go b/vendor/github.com/denverdino/aliyungo/util/util_test.go new file mode 100644 index 0000000000..c70eff02e1 --- /dev/null +++ b/vendor/github.com/denverdino/aliyungo/util/util_test.go @@ -0,0 +1,50 @@ +package util + +import ( + "testing" +) + +func TestCreateRandomString(t *testing.T) { + for i := 0; i < 10; i++ { + s := CreateRandomString() + t.Logf("Generated Random String: %s", s) + } +} + +func TestGenerateRandomECSPassword(t *testing.T) { + for i := 0; i < 10; i++ { + s := GenerateRandomECSPassword() + + if len(s) < 8 || len(s) > 30 { + t.Errorf("Generated ECS password [%v]: bad len", s) + } + + hasDigit := false + hasLower := false + hasUpper := false + + for j := range s { + + switch { + case '0' <= s[j] && s[j] <= '9': + hasDigit = true + case 'a' <= s[j] && s[j] <= 'z': + hasLower = true + case 'A' <= s[j] && s[j] <= 'Z': + hasUpper = true + } + } + + if !hasDigit { + t.Errorf("Generated ECS password [%v]: no digit", s) + } + + if !hasLower { + t.Errorf("Generated ECS password [%v]: no lower letter ", s) + } + + if !hasUpper { + t.Errorf("Generated ECS password [%v]: no upper letter", s) + } + } +}