You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by an...@apache.org on 2018/09/12 04:25:18 UTC
[1/7] jclouds-labs git commit: [JCLOUDS-1430] Aliyun ECS
Repository: jclouds-labs
Updated Branches:
refs/heads/master a5dbf0065 -> 2c7db7e80
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/instances-first.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/instances-first.json b/aliyun-ecs/src/test/resources/instances-first.json
new file mode 100644
index 0000000..23265a0
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/instances-first.json
@@ -0,0 +1,960 @@
+{
+ "PageNumber": 1,
+ "TotalCount": 20,
+ "PageSize": 10,
+ "RequestId": "D29E9D37-C372-41C2-8E9D-1E5F49042DE4",
+ "Instances": {
+ "Instance": [
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea1",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea2",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea3",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea4",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea5",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea6",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea7",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea8",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea9",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea10",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/instances-last.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/instances-last.json b/aliyun-ecs/src/test/resources/instances-last.json
new file mode 100644
index 0000000..75df755
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/instances-last.json
@@ -0,0 +1,960 @@
+{
+ "PageNumber": 2,
+ "TotalCount": 20,
+ "PageSize": 10,
+ "RequestId": "D29E9D37-1S72-41C2-8E9D-1E5F49042DE1",
+ "Instances": {
+ "Instance": [
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea11",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea12",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea13",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea14",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea15",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea16",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea17",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea18",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea19",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ },
+ {
+ "InnerIpAddress": {
+ "IpAddress": []
+ },
+ "ImageId": "centos_7_04_64_20G_alibase_20180419.vhd",
+ "InstanceTypeFamily": "ecs.t5",
+ "VlanId": "",
+ "NetworkInterfaces": {
+ "NetworkInterface": [
+ {
+ "MacAddress": "00:16:3e:00:75:cc",
+ "PrimaryIpAddress": "192.168.0.141",
+ "NetworkInterfaceId": "eni-gw8d5xjpg9ses2u4jhx3"
+ }
+ ]
+ },
+ "InstanceId": "i-gw8d5xjpg9ses2u0tcea20",
+ "EipAddress": {
+ "IpAddress": "",
+ "AllocationId": "",
+ "InternetChargeType": ""
+ },
+ "InternetMaxBandwidthIn": 0,
+ "ZoneId": "eu-central-1a",
+ "InternetChargeType": "PayByTraffic",
+ "SpotStrategy": "NoSpot",
+ "StoppedMode": "Not-applicable",
+ "SerialNumber": "6061c6ea-b7c1-49f0-9fe7-4444377df09a",
+ "IoOptimized": true,
+ "Memory": 512,
+ "Cpu": 1,
+ "VpcAttributes": {
+ "NatIpAddress": "",
+ "PrivateIpAddress": {
+ "IpAddress": [
+ "192.168.0.141"
+ ]
+ },
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ },
+ "InternetMaxBandwidthOut": 5,
+ "DeviceAvailable": true,
+ "SecurityGroupIds": {
+ "SecurityGroupId": [
+ "sg-gw8a9zlvmuyirwxlwsc1"
+ ]
+ },
+ "SaleCycle": "",
+ "SpotPriceLimit": 0.0,
+ "AutoReleaseTime": "",
+ "StartTime": "2018-06-25T19:02Z",
+ "KeyPairName": "jclouds",
+ "InstanceName": "jclouds",
+ "Description": "",
+ "ResourceGroupId": "",
+ "OSType": "linux",
+ "OSName": "CentOS 7.4 64[0xe4][0xbd][0x8d]",
+ "InstanceNetworkType": "vpc",
+ "PublicIpAddress": {
+ "IpAddress": [
+ "47.254.152.220"
+ ]
+ },
+ "HostName": "jclouds",
+ "InstanceType": "ecs.t5-lc2m1.nano",
+ "CreationTime": "2018-06-25T19:01Z",
+ "Tags": {
+ "Tag": [
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "jclouds_tags"
+ },
+ {
+ "TagValue": "aliyun-ecss",
+ "TagKey": "test"
+ }
+ ]
+ },
+ "Status": "Running",
+ "ClusterId": "",
+ "Recyclable": false,
+ "RegionId": "eu-central-1",
+ "GPUSpec": "",
+ "DedicatedHostAttribute": {
+ "DedicatedHostId": "",
+ "DedicatedHostName": ""
+ },
+ "OperationLocks": {
+ "LockReason": []
+ },
+ "InstanceChargeType": "PostPaid",
+ "GPUAmount": 0,
+ "ExpiredTime": "2099-12-31T15:59Z"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/logback-test.xml
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/logback-test.xml b/aliyun-ecs/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..eecf22d
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/logback-test.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<configuration scan="false">
+ <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+ <file>./target/test-data/jclouds.log</file>
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+ <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+ <file>./target/test-data/jclouds-wire.log</file>
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+ <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
+ <file>./target/test-data/jclouds-compute.log</file>
+ <encoder>
+ <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.jclouds">
+ <level value="DEBUG" />
+ <appender-ref ref="FILE" />
+ </logger>
+ <logger name="jclouds.compute">
+ <level value="DEBUG" />
+ <appender-ref ref="COMPUTEFILE" />
+ </logger>
+ <logger name="jclouds.wire">
+ <level value="DEBUG" />
+ <appender-ref ref="WIREFILE" />
+ </logger>
+ <logger name="jclouds.headers">
+ <level value="DEBUG" />
+ <appender-ref ref="WIREFILE" />
+ </logger>
+
+ <root>
+ <level value="INFO" />
+ </root>
+</configuration>
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vpc-create-res.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vpc-create-res.json b/aliyun-ecs/src/test/resources/vpc-create-res.json
new file mode 100644
index 0000000..7c17ad3
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vpc-create-res.json
@@ -0,0 +1,6 @@
+{
+ "RequestId": "461D0C42-D5D1-4009-9B6A-B3D5888A19A9",
+ "RouteTableId": "vtb-25wm68mnh",
+ "VRouterId": "vrt-25bezkd03",
+ "VpcId": "vpc-257gq642n"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vpc-delete-res.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vpc-delete-res.json b/aliyun-ecs/src/test/resources/vpc-delete-res.json
new file mode 100644
index 0000000..81b74f1
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vpc-delete-res.json
@@ -0,0 +1,3 @@
+{
+ "RequestId": "0ED8D006-F706-4D23-88ED-E11ED28DCAC0"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vpcs-first.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vpcs-first.json b/aliyun-ecs/src/test/resources/vpcs-first.json
new file mode 100644
index 0000000..9d229a0
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vpcs-first.json
@@ -0,0 +1,29 @@
+{
+ "PageNumber": 1,
+ "TotalCount": 2,
+ "Vpcs": {
+ "Vpc": [
+ {
+ "CreationTime": "2018-06-19T12:43:22Z",
+ "CidrBlock": "192.168.0.0/16",
+ "VpcName": "default",
+ "Status": "Available",
+ "Description": "",
+ "VSwitchIds": {
+ "VSwitchId": [
+ "vsw-gw8c79bsp4ezbe34ij3w8"
+ ]
+ },
+ "IsDefault": false,
+ "UserCidrs": {
+ "UserCidr": []
+ },
+ "RegionId": "eu-central-1",
+ "VRouterId": "vrt-gw8rs2qwhlasfwtqozz3q",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ }
+ ]
+ },
+ "PageSize": 1,
+ "RequestId": "F237893B-BC7A-4A3D-B952-6795D6590C4B"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vpcs-last.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vpcs-last.json b/aliyun-ecs/src/test/resources/vpcs-last.json
new file mode 100644
index 0000000..cb377ac
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vpcs-last.json
@@ -0,0 +1,29 @@
+{
+ "PageNumber": 2,
+ "TotalCount": 2,
+ "Vpcs": {
+ "Vpc": [
+ {
+ "CreationTime": "2018-06-19T12:43:23Z",
+ "CidrBlock": "192.168.1.0/16",
+ "VpcName": "test",
+ "Status": "Available",
+ "Description": "",
+ "VSwitchIds": {
+ "VSwitchId": [
+ "vsw-gw8c79bsp4ezbe34ij3w8"
+ ]
+ },
+ "IsDefault": false,
+ "UserCidrs": {
+ "UserCidr": []
+ },
+ "RegionId": "eu-central-1",
+ "VRouterId": "vrt-gw8rs2qwhlasfwtqozz3a",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhe"
+ }
+ ]
+ },
+ "PageSize": 1,
+ "RequestId": "F237893B-BC7A-4A3D-B952-6795D6590C4A"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vswitch-create-res.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vswitch-create-res.json b/aliyun-ecs/src/test/resources/vswitch-create-res.json
new file mode 100644
index 0000000..759faca
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vswitch-create-res.json
@@ -0,0 +1,4 @@
+{
+ "RequestId": "861E6630-AEC0-4B2D-B214-6CB5E44B7F04",
+ "VSwitchId": "vsw-25naue4gz"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vswitch-delete-res.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vswitch-delete-res.json b/aliyun-ecs/src/test/resources/vswitch-delete-res.json
new file mode 100644
index 0000000..971156c
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vswitch-delete-res.json
@@ -0,0 +1,3 @@
+{
+ "RequestId": "AF083E3D-7E29-4B77-A937-1F129802D5F3"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vswitches-first.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vswitches-first.json b/aliyun-ecs/src/test/resources/vswitches-first.json
new file mode 100644
index 0000000..3250ff0
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vswitches-first.json
@@ -0,0 +1,22 @@
+{
+ "PageNumber": 1,
+ "VSwitches": {
+ "VSwitch": [
+ {
+ "CreationTime": "2018-07-17T09:38:54Z",
+ "CidrBlock": "172.16.1.0/24",
+ "Status": "Available",
+ "Description": "",
+ "IsDefault": false,
+ "AvailableIpAddressCount": 252,
+ "VSwitchName": "jclouds-vswitch",
+ "ZoneId": "eu-central-1a",
+ "VSwitchId": "vsw-gw8rg87kqcw1kh2qms0pj",
+ "VpcId": "vpc-gw8myavcsj64kfpp92kd0"
+ }
+ ]
+ },
+ "TotalCount": 2,
+ "PageSize": 1,
+ "RequestId": "58A5DDE8-DFAE-42E8-AAC8-61D385CCA8A0"
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/vswitches-last.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/vswitches-last.json b/aliyun-ecs/src/test/resources/vswitches-last.json
new file mode 100644
index 0000000..14258ed
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/vswitches-last.json
@@ -0,0 +1,22 @@
+{
+ "PageNumber": 2,
+ "VSwitches": {
+ "VSwitch": [
+ {
+ "CreationTime": "2018-06-19T12:44:58Z",
+ "CidrBlock": "192.168.0.0/24",
+ "Status": "Available",
+ "Description": "",
+ "IsDefault": false,
+ "AvailableIpAddressCount": 252,
+ "VSwitchName": "default-fra1-a",
+ "ZoneId": "eu-central-1a",
+ "VSwitchId": "vsw-gw8c79bsp4ezbe34ij3w8",
+ "VpcId": "vpc-gw8vbir5z9j9lncyrjjhx"
+ }
+ ]
+ },
+ "TotalCount": 2,
+ "PageSize": 1,
+ "RequestId": "58A5DDE8-DFAE-42E8-AAC8-61D385CCA8A1"
+}
\ No newline at end of file
[4/7] jclouds-labs git commit: [JCLOUDS-1430] Aliyun ECS
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSTemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSTemplateBuilderLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSTemplateBuilderLiveTest.java
new file mode 100644
index 0000000..6c0343b
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSTemplateBuilderLiveTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute;
+
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
+import org.testng.annotations.Test;
+
+import java.util.Set;
+
+import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
+import static org.testng.Assert.assertEquals;
+
+@Test(groups = "live", testName = "ECSTemplateBuilderLiveTest")
+public class ECSTemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
+
+ public ECSTemplateBuilderLiveTest() {
+ provider = "alibaba-ecs";
+ }
+
+ @Test
+ @Override
+ public void testDefaultTemplateBuilder() {
+ Template defaultTemplate = view.getComputeService().templateBuilder().build();
+ assert defaultTemplate.getImage().getOperatingSystem().getVersion().startsWith("7.") : defaultTemplate.getImage()
+ .getOperatingSystem().getVersion();
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
+ assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
+ assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
+ }
+
+ @Override
+ protected Set<String> getIso3166Codes() {
+ return ImmutableSet.of("US-CA", "US-VA", "DE", "JP", "ID-JK", "SG", "IN", "AU-NSW", "MY", "CN-HE", "CN-SH", "CN-ZJ", "CN-GD", "HK", "AE-DU");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiLiveTest.java
index 5fe5c3f..f9e0e66 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiLiveTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiLiveTest.java
@@ -20,14 +20,13 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiLiveTest;
import org.jclouds.aliyun.ecs.domain.Image;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
+import org.jclouds.aliyun.ecs.domain.options.ListImagesOptions;
import org.jclouds.aliyun.ecs.features.ImageApi;
import org.testng.annotations.Test;
import java.util.concurrent.atomic.AtomicInteger;
-import static org.jclouds.aliyun.ecs.domain.options.ListImagesOptions.Builder.imageIds;
-import static org.jclouds.aliyun.ecs.domain.options.PaginationOptions.Builder.pageNumber;
+import static org.jclouds.aliyun.ecs.domain.options.PaginationOptions.Builder.pageSize;
import static org.testng.Assert.assertTrue;
import static org.testng.util.Strings.isNullOrEmpty;
@@ -36,7 +35,7 @@ public class ImageApiLiveTest extends BaseECSComputeServiceApiLiveTest {
public void testList() {
final AtomicInteger found = new AtomicInteger(0);
- assertTrue(Iterables.all(api().list(Regions.EU_CENTRAL_1.getName()).concat(), new Predicate<Image>() {
+ assertTrue(Iterables.all(api().list(TEST_REGION).concat(), new Predicate<Image>() {
@Override
public boolean apply(Image input) {
found.incrementAndGet();
@@ -48,9 +47,9 @@ public class ImageApiLiveTest extends BaseECSComputeServiceApiLiveTest {
public void testListWithOptions() {
final AtomicInteger found = new AtomicInteger(0);
- assertTrue(api().list(Regions.EU_CENTRAL_1.getName(),
- imageIds("debian_8_09_64_20G_alibase_20170824.vhd")
- .paginationOptions(pageNumber(3)))
+ assertTrue(api().list(TEST_REGION,
+ ListImagesOptions.Builder.imageName("debian_8_09_64_20G_alibase_20170824.vhd")
+ .paginationOptions(pageSize(1)))
.firstMatch(new Predicate<Image>() {
@Override
public boolean apply(Image input) {
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiMockTest.java
index e61b910..d206e8d 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiMockTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/ImageApiMockTest.java
@@ -19,7 +19,6 @@ package org.jclouds.aliyun.ecs.compute.features;
import com.google.common.collect.ImmutableMap;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
import org.jclouds.aliyun.ecs.domain.Image;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.testng.annotations.Test;
import static com.google.common.collect.Iterables.isEmpty;
@@ -36,35 +35,35 @@ public class ImageApiMockTest extends BaseECSComputeServiceApiMockTest {
server.enqueue(jsonResponse("/images-first.json"));
server.enqueue(jsonResponse("/images-second.json"));
server.enqueue(jsonResponse("/images-last.json"));
- Iterable<Image> images = api.imageApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<Image> images = api.imageApi().list(TEST_REGION).concat();
assertEquals(size(images), 28); // Force the PagedIterable to advance
assertEquals(server.getRequestCount(), 3);
- assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
- assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 2);
- assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 3);
+ assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", TEST_REGION));
+ assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", TEST_REGION), 2);
+ assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", TEST_REGION), 3);
}
public void testListImagesReturns404() {
server.enqueue(response404());
- Iterable<Image> images = api.imageApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<Image> images = api.imageApi().list(TEST_REGION).concat();
assertTrue(isEmpty(images));
assertEquals(server.getRequestCount(), 1);
}
public void testListImagesWithOptions() throws InterruptedException {
server.enqueue(jsonResponse("/images-first.json"));
- Iterable<Image> images = api.imageApi().list(Regions.EU_CENTRAL_1.getName(), paginationOptions(pageNumber(1)));
+ Iterable<Image> images = api.imageApi().list(TEST_REGION, paginationOptions(pageNumber(1)));
assertEquals(size(images), 10);
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", TEST_REGION));
}
public void testListImagesWithOptionsReturns404() throws InterruptedException {
server.enqueue(response404());
- Iterable<Image> images = api.imageApi().list(Regions.EU_CENTRAL_1.getName(), paginationOptions(pageNumber(2)));
+ Iterable<Image> images = api.imageApi().list(TEST_REGION, paginationOptions(pageNumber(2)));
assertTrue(isEmpty(images));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 2);
+ assertSent(server, "GET", "DescribeImages", ImmutableMap.of("RegionId", TEST_REGION), 2);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiLiveTest.java
new file mode 100644
index 0000000..1b987fd
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiLiveTest.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.features;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.Uninterruptibles;
+import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiLiveTest;
+import org.jclouds.aliyun.ecs.domain.AvailableZone;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.InstanceRequest;
+import org.jclouds.aliyun.ecs.domain.InstanceStatus;
+import org.jclouds.aliyun.ecs.domain.InstanceType;
+import org.jclouds.aliyun.ecs.domain.SecurityGroupRequest;
+import org.jclouds.aliyun.ecs.domain.VPC;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.VSwitchRequest;
+import org.jclouds.aliyun.ecs.domain.options.CreateInstanceOptions;
+import org.jclouds.aliyun.ecs.domain.options.CreateSecurityGroupOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListInstancesOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVPCsOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.aliyun.ecs.features.InstanceApi;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes.DEFAULT_CIDR_BLOCK;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.util.Strings.isNullOrEmpty;
+
+@Test(groups = "live", testName = "InstanceApiLiveTest")
+public class InstanceApiLiveTest extends BaseECSComputeServiceApiLiveTest {
+
+ private String imageId = "ubuntu_16_0402_32_20G_alibase_20180409.vhd";
+ private String hostname = "jclouds-test";
+ private String instanceType = "ecs.t5-lc2m1.nano";
+ private String vpcId;
+ private String vSwitchId;
+ private String securityGroupId;
+ private String instanceId;
+ private String slashEncodedInstanceId;
+
+ @BeforeClass
+ public void setUp() {
+ VPCRequest vpcRequest = api.vpcApi().create(TEST_REGION);
+ vpcId = vpcRequest.getVpcId();
+ VPC vpc = api.vpcApi().list(TEST_REGION, ListVPCsOptions.Builder.vpcId(vpcId)).firstMatch(Predicates.notNull()).orNull();
+ while (vpc == null || vpc.status() == VPC.Status.PENDING) {
+ vpc = api.vpcApi().list(TEST_REGION, ListVPCsOptions.Builder.vpcId(vpcId)).firstMatch(Predicates.notNull()).orNull();
+ Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS);
+ }
+
+ VSwitchRequest vSwitchRequest = api.vSwitchApi().create(TEST_ZONE, DEFAULT_CIDR_BLOCK, vpcId);
+ vSwitchId = vSwitchRequest.getVSwitchId();
+ VSwitch vSwitch = api.vSwitchApi().list(TEST_REGION, ListVSwitchesOptions.Builder.vSwitchId(vSwitchId)).firstMatch(Predicates.notNull()).orNull();
+ while (vSwitch == null || vSwitch.status() == VSwitch.Status.PENDING) {
+ vSwitch = api.vSwitchApi().list(TEST_REGION, ListVSwitchesOptions.Builder.vSwitchId(vSwitchId)).firstMatch(Predicates.notNull()).orNull();
+ Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS);
+ }
+
+ SecurityGroupRequest request = api.securityGroupApi().create(TEST_REGION,
+ CreateSecurityGroupOptions.Builder
+ .securityGroupName(InstanceApiLiveTest.class.getSimpleName())
+ .vpcId(vpcId)
+ );
+ securityGroupId = request.getSecurityGroupId();
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void tearDown() {
+ if (instanceId != null) {
+ api().delete(instanceId);
+ }
+
+ if (securityGroupId != null) {
+ api.securityGroupApi().delete(TEST_REGION, securityGroupId);
+ }
+
+ if (vSwitchId != null) {
+ api.vSwitchApi().delete(TEST_REGION, vSwitchId);
+ }
+
+ if (vpcId != null) {
+ api.vpcApi().delete(TEST_REGION, vpcId);
+ }
+ }
+
+ public void testListInstanceTypeByAvailableZone() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(Iterables.all(api().listInstanceTypesByAvailableZone(TEST_REGION), new Predicate<AvailableZone>() {
+ @Override
+ public boolean apply(AvailableZone input) {
+ found.incrementAndGet();
+ return !input.availableResources().isEmpty();
+ }
+ }), "All available zones must have the 'id' field populated");
+ assertTrue(found.get() > 0, "Expected some instance type to be returned");
+ }
+
+ public void testListInstanceType() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(Iterables.all(api().listTypes(), new Predicate<InstanceType>() {
+ @Override
+ public boolean apply(InstanceType input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.id());
+ }
+ }), "All instance types must have the 'id' field populated");
+ assertTrue(found.get() > 0, "Expected some instance type to be returned");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testListInstanceType")
+ public void testListInstance() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(Iterables.all(api().list(TEST_REGION).concat(), new Predicate<Instance>() {
+ @Override
+ public boolean apply(Instance input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.id());
+ }
+ }), "All instances must have the 'id' field populated");
+ }
+
+ @Test(groups = "live")
+ public void testCreate() {
+ InstanceRequest instanceRequest = api().create(TEST_REGION, imageId, securityGroupId, hostname, instanceType,
+ CreateInstanceOptions.Builder.vSwitchId(vSwitchId));
+ instanceId = instanceRequest.getInstanceId();
+ slashEncodedInstanceId = RegionAndId.slashEncodeRegionAndId(TEST_REGION, instanceId);
+ assertNotNull(instanceId, "Instance id must not be null");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testCreate")
+ public void testGet() {
+ Instance instance = Iterables.getOnlyElement(api().list(TEST_REGION,
+ ListInstancesOptions.Builder.instanceIds(instanceId)));
+ assertNotNull(instance.id(), "Instance must not be null");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testCreate")
+ public void testListInstanceStatus() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(Iterables.all(api().listInstanceStatus(TEST_REGION).concat(), new Predicate<InstanceStatus>() {
+ @Override
+ public boolean apply(InstanceStatus input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.instanceId());
+ }
+ }), "All instance status must have the 'instance id' field populated");
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testGet")
+ public void testStartInstance() {
+ api().powerOn(instanceId);
+ assertTrue(instanceRunningPredicate.apply(slashEncodedInstanceId));
+ }
+
+ @Test(groups = "live", dependsOnMethods = "testStartInstance")
+ public void testStopInstance() {
+ api().powerOff(instanceId);
+ assertTrue(instanceSuspendedPredicate.apply(slashEncodedInstanceId));
+ }
+
+ private InstanceApi api() {
+ return api.instanceApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiMockTest.java
new file mode 100644
index 0000000..95609b9
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/InstanceApiMockTest.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.features;
+
+import com.google.common.collect.Iterables;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
+import org.jclouds.aliyun.ecs.domain.AvailableZone;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.InstanceStatus;
+import org.jclouds.aliyun.ecs.domain.InstanceType;
+import org.jclouds.aliyun.ecs.domain.options.CreateInstanceOptions;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "unit", testName = "InstanceApiMockTest", singleThreaded = true)
+public class InstanceApiMockTest extends BaseECSComputeServiceApiMockTest {
+
+ public void testListInstances() throws InterruptedException {
+ server.enqueue(jsonResponse("/instances-first.json"));
+ server.enqueue(jsonResponse("/instances-last.json"));
+
+ Iterable<Instance> instances = api.instanceApi().list(TEST_REGION).concat();
+ assertEquals(size(instances), 20); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+ assertSent(server, "GET", "DescribeInstances");
+ assertSent(server, "GET", "DescribeInstances", 2);
+ }
+
+ public void testListInstancesReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ Iterable<Instance> instances = api.instanceApi().list(TEST_REGION).concat();
+ assertTrue(isEmpty(instances));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeInstances");
+ }
+
+ public void testListInstanceTypes() throws InterruptedException {
+ server.enqueue(jsonResponse("/instanceTypes.json"));
+
+ List<InstanceType> instanceTypes = api.instanceApi().listTypes();
+ assertEquals(size(instanceTypes), 308);
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeInstanceTypes");
+ }
+
+ public void testListInstanceTypesReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ List<InstanceType> instanceTypes = api.instanceApi().listTypes();
+ assertTrue(isEmpty(instanceTypes));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeInstanceTypes");
+ }
+
+ public void testListInstanceTypesByAvailableZone() throws InterruptedException {
+ server.enqueue(jsonResponse("/availableZones.json"));
+
+ List<AvailableZone> availableZones = api.instanceApi().listInstanceTypesByAvailableZone(TEST_REGION);
+ assertEquals(size(availableZones), 2);
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeAvailableResource");
+ }
+
+ public void testListInstanceTypesByAvailableZoneReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ List<AvailableZone> availableZones = api.instanceApi().listInstanceTypesByAvailableZone(TEST_REGION);
+ assertTrue(isEmpty(availableZones));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeAvailableResource");
+ }
+
+ public void testCreateInstance() throws InterruptedException {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{" +
+ " \"RequestId\": \"04F0F334-1335-436C-A1D7-6C044FE73368\"," +
+ " \"InstanceId\": \"i-instance1\"" +
+ "}"));
+ api.instanceApi().create(TEST_REGION,
+ "test",
+ "SecurityGroupId",
+ "Hostname",
+ "InstanceType"
+ );
+ assertSent(server, "POST", "CreateInstance");
+ }
+
+ public void testCreateInstanceWithInstanceName() throws InterruptedException {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{" +
+ " \"RequestId\": \"04F0F334-1335-436C-A1D7-6C044FE73368\"," +
+ " \"InstanceId\": \"i-instance1\"" +
+ "}"));
+ api.instanceApi().create(TEST_REGION,
+ "test",
+ "SecurityGroupId",
+ "Hostname",
+ "InstanceType",
+ CreateInstanceOptions.Builder.instanceName("jclouds")
+ );
+ assertSent(server, "POST", "CreateInstance");
+ }
+
+ public void testAllocatePublicIpAddress() throws InterruptedException {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{" +
+ " \"RequestId\": \"F2EF6A3B-E345-46B9-931E-0EA094818567\"," +
+ " \"IpAddress\": \"10.1.149.159\"" +
+ "}"));
+ api.instanceApi().create(TEST_REGION,
+ "test",
+ "SecurityGroupId",
+ "Hostname",
+ "InstanceType"
+ );
+ assertSent(server, "POST", "CreateInstance");
+ }
+
+ public void testGetStatus() throws Exception {
+ server.enqueue(jsonResponse("/instanceStatus.json"));
+ Iterable<InstanceStatus> instanceStatuses = api.instanceApi().listInstanceStatus("12345").concat();
+ assertSent(server, "GET", "DescribeInstanceStatus");
+ assertNotNull(instanceStatuses);
+ }
+
+ public void testGetStatusReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ Iterable<InstanceStatus> instanceStatuses = api.instanceApi().listInstanceStatus("12345").concat();
+ assertTrue(Iterables.isEmpty(instanceStatuses));
+ assertSent(server, "GET", "DescribeInstanceStatus");
+ }
+
+ public void testDeleteInstance() throws Exception {
+ server.enqueue(new MockResponse().setResponseCode(200).setBody(
+ "{" +
+ " \"RequestId\": \"928E2273-5715-46B9-A730-238DC996A533\"" +
+ "}"));
+ api.instanceApi().delete("instanceId");
+ assertSent(server, "POST", "DeleteInstance");
+ }
+
+ public void testDeleteInstanceReturns404() throws Exception {
+ server.enqueue(response404());
+ api.instanceApi().delete("instanceId");
+ assertSent(server, "POST", "DeleteInstance");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/RegionAndZoneApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/RegionAndZoneApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/RegionAndZoneApiMockTest.java
index e116845..46badaf 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/RegionAndZoneApiMockTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/RegionAndZoneApiMockTest.java
@@ -19,7 +19,6 @@ package org.jclouds.aliyun.ecs.compute.features;
import com.google.common.collect.ImmutableMap;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
import org.jclouds.aliyun.ecs.domain.Region;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.aliyun.ecs.domain.Zone;
import org.testng.annotations.Test;
@@ -51,18 +50,18 @@ public class RegionAndZoneApiMockTest extends BaseECSComputeServiceApiMockTest {
public void testListZones() throws InterruptedException {
server.enqueue(jsonResponse("/zones.json"));
- List<Zone> zones = api.regionAndZoneApi().describeZones(Regions.EU_CENTRAL_1.getName());
+ List<Zone> zones = api.regionAndZoneApi().describeZones(TEST_REGION);
assertEquals(size(zones), 2);
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeZones", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "GET", "DescribeZones", ImmutableMap.of("RegionId", TEST_REGION));
}
public void testListZonesReturns404() throws InterruptedException {
server.enqueue(response404());
- List<Zone> zones = api.regionAndZoneApi().describeZones(Regions.EU_CENTRAL_1.getName());
+ List<Zone> zones = api.regionAndZoneApi().describeZones(TEST_REGION);
assertTrue(isEmpty(zones));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeZones", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "GET", "DescribeZones", ImmutableMap.of("RegionId", TEST_REGION));
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiLiveTest.java
index 5c76fc5..6fde29e 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiLiveTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiLiveTest.java
@@ -21,7 +21,6 @@ import com.google.common.collect.Iterables;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiLiveTest;
import org.jclouds.aliyun.ecs.domain.IpProtocol;
import org.jclouds.aliyun.ecs.domain.Permission;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.aliyun.ecs.domain.SecurityGroup;
import org.jclouds.aliyun.ecs.domain.SecurityGroupRequest;
import org.jclouds.aliyun.ecs.domain.options.CreateSecurityGroupOptions;
@@ -46,7 +45,7 @@ public class SecurityGroupApiLiveTest extends BaseECSComputeServiceApiLiveTest {
@BeforeClass
public void setUp() {
- SecurityGroupRequest request = api().create(Regions.EU_CENTRAL_1.getName(),
+ SecurityGroupRequest request = api().create(TEST_REGION,
CreateSecurityGroupOptions.Builder
.securityGroupName("jclouds-test")
);
@@ -56,24 +55,24 @@ public class SecurityGroupApiLiveTest extends BaseECSComputeServiceApiLiveTest {
@AfterClass
public void tearDown() {
if (securityGroupId != null) {
- api().delete(Regions.EU_CENTRAL_1.getName(), securityGroupId);
+ api().delete(TEST_REGION, securityGroupId);
}
}
public void testAddRules() {
- api().addInboundRule(Regions.EU_CENTRAL_1.getName(), securityGroupId, IpProtocol.TCP, TEST_PORT_RANGE, INTERNET);
+ api().addInboundRule(TEST_REGION, securityGroupId, IpProtocol.TCP, TEST_PORT_RANGE, INTERNET);
}
@Test(groups = "live", dependsOnMethods = "testAddRules")
public void testGet() {
- Permission permission = Iterables.getOnlyElement(api().get(Regions.EU_CENTRAL_1.getName(), securityGroupId));
+ Permission permission = Iterables.getOnlyElement(api().get(TEST_REGION, securityGroupId));
checkPermission(permission);
}
@Test(groups = "live", dependsOnMethods = "testGet")
public void testList() {
final AtomicInteger found = new AtomicInteger(0);
- assertTrue(Iterables.all(api().list(Regions.EU_CENTRAL_1.getName()).concat(), new Predicate<SecurityGroup>() {
+ assertTrue(Iterables.all(api().list(TEST_REGION).concat(), new Predicate<SecurityGroup>() {
@Override
public boolean apply(SecurityGroup input) {
found.incrementAndGet();
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiMockTest.java
index 46aa76b..a7999a3 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiMockTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SecurityGroupApiMockTest.java
@@ -18,7 +18,6 @@ package org.jclouds.aliyun.ecs.compute.features;
import com.google.common.collect.ImmutableMap;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.aliyun.ecs.domain.SecurityGroup;
import org.testng.annotations.Test;
@@ -35,35 +34,35 @@ public class SecurityGroupApiMockTest extends BaseECSComputeServiceApiMockTest {
public void testListSecurityGroups() throws InterruptedException {
server.enqueue(jsonResponse("/securitygroups-first.json"));
server.enqueue(jsonResponse("/securitygroups-last.json"));
- Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(TEST_REGION).concat();
assertEquals(size(securitygroups), 7); // Force the PagedIterable to advance
assertEquals(server.getRequestCount(), 2);
- assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
- assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 2);
+ assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", TEST_REGION));
+ assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", TEST_REGION), 2);
}
public void testListSecurityGroupsReturns404() throws InterruptedException {
server.enqueue(response404());
- Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(TEST_REGION).concat();
assertTrue(isEmpty(securitygroups));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", TEST_REGION));
}
public void testListSecurityGroupsWithOptions() throws InterruptedException {
server.enqueue(jsonResponse("/securitygroups-first.json"));
- Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(Regions.EU_CENTRAL_1.getName(), paginationOptions(pageNumber(1).pageSize(5)));
+ Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(TEST_REGION, paginationOptions(pageNumber(1).pageSize(5)));
assertEquals(size(securitygroups), 5);
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 1);
+ assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", TEST_REGION), 1);
}
public void testListSecurityGroupsWithOptionsReturns404() throws InterruptedException {
server.enqueue(response404());
- Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(Regions.EU_CENTRAL_1.getName(), paginationOptions(pageNumber(2)));
+ Iterable<SecurityGroup> securitygroups = api.securityGroupApi().list(TEST_REGION, paginationOptions(pageNumber(2)));
assertTrue(isEmpty(securitygroups));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 2);
+ assertSent(server, "GET", "DescribeSecurityGroups", ImmutableMap.of("RegionId", TEST_REGION), 2);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiLiveTest.java
index 85ceee5..632e06e 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiLiveTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiLiveTest.java
@@ -21,9 +21,8 @@ import com.google.common.collect.Iterables;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiLiveTest;
import org.jclouds.aliyun.ecs.domain.KeyPair;
import org.jclouds.aliyun.ecs.domain.KeyPairRequest;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.aliyun.ecs.features.SshKeyPairApi;
-import org.jclouds.ssh.SshKeys;
+import org.jclouds.compute.ComputeTestUtils;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -43,22 +42,22 @@ public class SshKeyPairApiLiveTest extends BaseECSComputeServiceApiLiveTest {
@BeforeClass
public void setUp() {
- KeyPairRequest request = api().create(Regions.EU_CENTRAL_1.getName(), keyPairName);
+ KeyPairRequest request = api().create(TEST_REGION, keyPairName);
assertNotNull(request.getRequestId());
}
@AfterClass
public void tearDown() {
if (keyPairName != null) {
- api().delete(Regions.EU_CENTRAL_1.getName(), keyPairName);
+ api().delete(TEST_REGION, keyPairName);
}
}
public void testImport() {
String importedKeyPairName = keyPairName + new Random().nextInt(1024);
KeyPair imported = api().importKeyPair(
- Regions.EU_CENTRAL_1.getName(),
- SshKeys.generate().get("public"),
+ TEST_REGION,
+ ComputeTestUtils.setupKeyPair().get("public"), //SshKeys.generate().get("public"),
importedKeyPairName);
assertEquals(imported.name(), importedKeyPairName);
assertNotNull(imported.privateKeyBody());
@@ -67,7 +66,7 @@ public class SshKeyPairApiLiveTest extends BaseECSComputeServiceApiLiveTest {
public void testList() {
final AtomicInteger found = new AtomicInteger(0);
- assertTrue(Iterables.all(api().list(Regions.EU_CENTRAL_1.getName()).concat(), new Predicate<KeyPair>() {
+ assertTrue(Iterables.all(api().list(TEST_REGION).concat(), new Predicate<KeyPair>() {
@Override
public boolean apply(KeyPair input) {
found.incrementAndGet();
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiMockTest.java
index 23c21ad..78f5a39 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiMockTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/SshKeyPairApiMockTest.java
@@ -20,7 +20,6 @@ import com.google.common.collect.ImmutableMap;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
import org.jclouds.aliyun.ecs.domain.KeyPair;
import org.jclouds.aliyun.ecs.domain.KeyPairRequest;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.aliyun.ecs.domain.Request;
import org.jclouds.aliyun.ecs.domain.options.ListKeyPairsOptions;
import org.jclouds.aliyun.ecs.domain.options.PaginationOptions;
@@ -37,37 +36,37 @@ public class SshKeyPairApiMockTest extends BaseECSComputeServiceApiMockTest {
public void testCreateSshKey() throws InterruptedException {
server.enqueue(jsonResponse("/keypair-create-res.json"));
- KeyPairRequest keyPairRequest = api.sshKeyPairApi().create(Regions.EU_CENTRAL_1.getName(), "jclouds");
+ KeyPairRequest keyPairRequest = api.sshKeyPairApi().create(TEST_REGION, "jclouds");
assertEquals(keyPairRequest, objectFromResource("/keypair-create-res.json", KeyPairRequest.class));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "POST", "CreateKeyPair", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "POST", "CreateKeyPair", ImmutableMap.of("RegionId", TEST_REGION));
}
public void testDeleteSshKey() throws InterruptedException {
server.enqueue(jsonResponse("/keypair-delete-res.json"));
- Request delete = api.sshKeyPairApi().delete(Regions.EU_CENTRAL_1.getName());
+ Request delete = api.sshKeyPairApi().delete(TEST_REGION);
assertEquals(delete, objectFromResource("/keypair-delete-res.json", Request.class));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "POST", "DeleteKeyPairs", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "POST", "DeleteKeyPairs", ImmutableMap.of("RegionId", TEST_REGION));
}
public void testImportSshKey() throws InterruptedException {
server.enqueue(jsonResponse("/keypair-import-res.json"));
KeyPair keyPair = api.sshKeyPairApi().importKeyPair(
- Regions.EU_CENTRAL_1.getName(),
+ TEST_REGION,
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCdgcoNzH4hCc0j3b4MuG503L/J54uyFvwCAOu8vSsYuLpJ4AEyEOv+T0SfdF605fK6GYXA16Rxk3lrPt7mfKGNtXR0Ripbv7Zc6PvCRorwgj/cjh/45miozjrkXAiHD1GFZycfbi4YsoWAqZj7W4mwtctmhrYM0FPdya2XoRpVy89N+A5Xo4Xtd6EZn6JGEKQM5+kF2aL3ggy0od/DqjuEVYwZoyTe1RgUTXZSU/Woh7WMhsRHbqd3eYz4s6ac8n8IJPGKtUaQeqUtH7OK6NRYXVypUrkqNlwdNYZAwrjXg/x5T3D+bo11LENASRt9OJ2OkmRSTqRxBeDkhnVauWK/",
"jclouds"
);
assertEquals(keyPair, objectFromResource("/keypair-import-res.json", KeyPair.class));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "POST", "ImportKeyPair", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "POST", "ImportKeyPair", ImmutableMap.of("RegionId", TEST_REGION));
}
public void testListImages() throws InterruptedException {
server.enqueue(jsonResponse("/keypairs-first.json"));
server.enqueue(jsonResponse("/keypairs-last.json"));
- Iterable<KeyPair> keypairs = api.sshKeyPairApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<KeyPair> keypairs = api.sshKeyPairApi().list(TEST_REGION).concat();
assertEquals(size(keypairs), 12);
assertEquals(server.getRequestCount(), 2);
assertSent(server, "GET", "DescribeKeyPairs");
@@ -76,7 +75,7 @@ public class SshKeyPairApiMockTest extends BaseECSComputeServiceApiMockTest {
public void testListKeyPairsReturns404() {
server.enqueue(response404());
- Iterable<KeyPair> keypairs = api.sshKeyPairApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<KeyPair> keypairs = api.sshKeyPairApi().list(TEST_REGION).concat();
assertTrue(isEmpty(keypairs));
assertEquals(server.getRequestCount(), 1);
}
@@ -84,7 +83,7 @@ public class SshKeyPairApiMockTest extends BaseECSComputeServiceApiMockTest {
public void testListKeyPairsWithOptions() throws InterruptedException {
server.enqueue(jsonResponse("/keypairs-first.json"));
- IterableWithMarker<KeyPair> keypairs = api.sshKeyPairApi().list(Regions.EU_CENTRAL_1.getName(), ListKeyPairsOptions.Builder
+ IterableWithMarker<KeyPair> keypairs = api.sshKeyPairApi().list(TEST_REGION, ListKeyPairsOptions.Builder
.paginationOptions(PaginationOptions.Builder.pageNumber(1)));
assertEquals(size(keypairs), 10);
@@ -96,7 +95,7 @@ public class SshKeyPairApiMockTest extends BaseECSComputeServiceApiMockTest {
public void testListKeyPairsWithOptionsReturns404() throws InterruptedException {
server.enqueue(response404());
- IterableWithMarker<KeyPair> keypairs = api.sshKeyPairApi().list(Regions.EU_CENTRAL_1.getName(), ListKeyPairsOptions.Builder
+ IterableWithMarker<KeyPair> keypairs = api.sshKeyPairApi().list(TEST_REGION, ListKeyPairsOptions.Builder
.paginationOptions(PaginationOptions.Builder.pageNumber(2)));
assertTrue(isEmpty(keypairs));
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiLiveTest.java
index 854b494..cd07ae2 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiLiveTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiLiveTest.java
@@ -18,7 +18,6 @@ package org.jclouds.aliyun.ecs.compute.features;
import com.google.common.base.Predicate;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiLiveTest;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.aliyun.ecs.domain.Request;
import org.jclouds.aliyun.ecs.domain.SecurityGroupRequest;
import org.jclouds.aliyun.ecs.domain.Tag;
@@ -32,6 +31,7 @@ import org.testng.annotations.Test;
import java.util.concurrent.atomic.AtomicInteger;
+import static org.jclouds.aliyun.ecs.domain.ResourceType.SECURITYGROUP;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
@@ -40,38 +40,36 @@ import static org.testng.util.Strings.isNullOrEmpty;
@Test(groups = "live", testName = "TagApiLiveTest")
public class TagApiLiveTest extends BaseECSComputeServiceApiLiveTest {
- public static final String RESOURCE_TYPE = "securitygroup";
-
private String securityGroupName = "pre-test-security";
private String securityGroupId;
@BeforeClass
public void setUp() {
- SecurityGroupRequest preRequisite = api.securityGroupApi().create(Regions.EU_CENTRAL_1.getName(),
+ SecurityGroupRequest preRequisite = api.securityGroupApi().create(TEST_REGION,
CreateSecurityGroupOptions.Builder.securityGroupName(securityGroupName)
);
securityGroupId = preRequisite.getSecurityGroupId();
- Request request = api().add(Regions.EU_CENTRAL_1.getName(), securityGroupId, RESOURCE_TYPE,
+ Request request = api().add(TEST_REGION, securityGroupId, SECURITYGROUP,
TagOptions.Builder.tag(1, "owner"));
assertNotNull(request.getRequestId());
}
@AfterClass
public void tearDown() {
- api().remove(Regions.EU_CENTRAL_1.getName(), securityGroupId, RESOURCE_TYPE);
+ api().remove(TEST_REGION, securityGroupId, SECURITYGROUP);
if (securityGroupId != null) {
- api.securityGroupApi().delete(Regions.EU_CENTRAL_1.getName(), securityGroupId);
+ api.securityGroupApi().delete(TEST_REGION, securityGroupId);
}
}
public void testList() {
final AtomicInteger found = new AtomicInteger(0);
- assertFalse(api().list(Regions.EU_CENTRAL_1.getName(), ListTagsOptions.Builder.resourceId(securityGroupId))
+ assertFalse(api().list(TEST_REGION, ListTagsOptions.Builder.resourceId(securityGroupId))
.filter(new Predicate<Tag>() {
@Override
public boolean apply(Tag input) {
found.incrementAndGet();
- return !isNullOrEmpty(input.tagKey());
+ return !isNullOrEmpty(input.key());
}
}).isEmpty(), "All tags must have the 'key' field populated");
assertTrue(found.get() > 0, "Expected some tags to be returned");
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiMockTest.java
index deb492d..350a218 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiMockTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/TagApiMockTest.java
@@ -18,7 +18,6 @@ package org.jclouds.aliyun.ecs.compute.features;
import com.google.common.collect.ImmutableMap;
import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
-import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.aliyun.ecs.domain.Tag;
import org.testng.annotations.Test;
@@ -35,35 +34,35 @@ public class TagApiMockTest extends BaseECSComputeServiceApiMockTest {
public void testListTags() throws InterruptedException {
server.enqueue(jsonResponse("/tags-first.json"));
server.enqueue(jsonResponse("/tags-last.json"));
- Iterable<Tag> tags = api.tagApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<Tag> tags = api.tagApi().list(TEST_REGION).concat();
assertEquals(size(tags), 10); // Force the PagedIterable to advance
assertEquals(server.getRequestCount(), 2);
- assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
- assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 2);
+ assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", TEST_REGION));
+ assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", TEST_REGION), 2);
}
public void testListTagsReturns404() throws InterruptedException {
server.enqueue(response404());
- Iterable<Tag> tags = api.tagApi().list(Regions.EU_CENTRAL_1.getName()).concat();
+ Iterable<Tag> tags = api.tagApi().list(TEST_REGION).concat();
assertTrue(isEmpty(tags));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()));
+ assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", TEST_REGION));
}
public void testListTagsWithOptions() throws InterruptedException {
server.enqueue(jsonResponse("/tags-first.json"));
- Iterable<Tag> tags = api.tagApi().list(Regions.EU_CENTRAL_1.getName(), paginationOptions(pageNumber(1).pageSize(5)));
+ Iterable<Tag> tags = api.tagApi().list(TEST_REGION, paginationOptions(pageNumber(1).pageSize(5)));
assertEquals(size(tags), 8);
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 1);
+ assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", TEST_REGION), 1);
}
public void testListTagsWithOptionsReturns404() throws InterruptedException {
server.enqueue(response404());
- Iterable<Tag> tags = api.tagApi().list(Regions.EU_CENTRAL_1.getName(), paginationOptions(pageNumber(2)));
+ Iterable<Tag> tags = api.tagApi().list(TEST_REGION, paginationOptions(pageNumber(2)));
assertTrue(isEmpty(tags));
assertEquals(server.getRequestCount(), 1);
- assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", Regions.EU_CENTRAL_1.getName()), 2);
+ assertSent(server, "GET", "DescribeTags", ImmutableMap.of("RegionId", TEST_REGION), 2);
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiLiveTest.java
new file mode 100644
index 0000000..8d2639e
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiLiveTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.features;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiLiveTest;
+import org.jclouds.aliyun.ecs.domain.VPC;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.aliyun.ecs.domain.options.CreateVPCOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVPCsOptions;
+import org.jclouds.aliyun.ecs.features.VPCApi;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.jclouds.aliyun.ecs.domain.options.PaginationOptions.Builder.pageSize;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.util.Strings.isNullOrEmpty;
+
+@Test(groups = "live", testName = "VPCApiLiveTest")
+public class VPCApiLiveTest extends BaseECSComputeServiceApiLiveTest {
+
+ public static final String VPC_NAME = "jclouds-vpc";
+
+ private String vpcId;
+
+ @BeforeClass
+ public void setUp() {
+ VPCRequest vpcRequest = api().create(TEST_REGION, CreateVPCOptions.Builder.vpcName(VPC_NAME));
+ assertNotNull(vpcRequest.getRequestId());
+ assertNotNull(vpcRequest.getVpcId());
+ vpcId = vpcRequest.getVpcId();
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void tearDown() {
+ if (vpcId != null) {
+ assertNotNull(api().delete(TEST_REGION, vpcId));
+ }
+ }
+
+ public void testList() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(Iterables.all(api().list(TEST_REGION).concat(), new Predicate<VPC>() {
+ @Override
+ public boolean apply(VPC input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.id());
+ }
+ }), "All vpcs must have at least the 'id' field populated");
+ assertTrue(found.get() > 0, "Expected some vpc to be returned");
+ }
+
+ public void testListWithOptions() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(TEST_REGION, ListVPCsOptions.Builder.vpcId(vpcId)
+ .paginationOptions(pageSize(50)))
+ .firstMatch(new Predicate<VPC>() {
+ @Override
+ public boolean apply(VPC input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.id());
+ }
+ }).isPresent(), "All vpcs must have the 'id' field populated");
+ assertTrue(found.get() > 0, "Expected some image to be returned");
+ }
+
+ private VPCApi api() {
+ return api.vpcApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiMockTest.java
new file mode 100644
index 0000000..80de7f3
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VPCApiMockTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.features;
+
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
+import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.VPC;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.collect.IterableWithMarker;
+import org.testng.annotations.Test;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.aliyun.ecs.domain.options.ListVPCsOptions.Builder.paginationOptions;
+import static org.jclouds.aliyun.ecs.domain.options.PaginationOptions.Builder.pageNumber;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "unit", testName = "VPCApiMockTest", singleThreaded = true)
+public class VPCApiMockTest extends BaseECSComputeServiceApiMockTest {
+
+ public void testListVPCs() throws InterruptedException {
+ server.enqueue(jsonResponse("/vpcs-first.json"));
+ server.enqueue(jsonResponse("/vpcs-last.json"));
+ Iterable<VPC> vpcs = api.vpcApi().list(TEST_REGION).concat();
+ assertEquals(size(vpcs), 2); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+ assertSent(server, "GET", "DescribeVpcs", ImmutableMap.of("RegionId", TEST_REGION));
+ assertSent(server, "GET", "DescribeVpcs", ImmutableMap.of("RegionId", TEST_REGION), 2);
+ }
+
+ public void testListVPCsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ Iterable<VPC> vpcs = api.vpcApi().list(TEST_REGION).concat();
+ assertTrue(isEmpty(vpcs));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeVpcs", ImmutableMap.of("RegionId", TEST_REGION));
+ }
+
+ public void testListVPCsWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/vpcs-first.json"));
+ IterableWithMarker<VPC> vpcs = api.vpcApi().list(TEST_REGION, paginationOptions(pageNumber(1).pageSize(5)));
+ assertEquals(size(vpcs), 1);
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeVpcs", ImmutableMap.of("RegionId", TEST_REGION), 1);
+ }
+
+ public void testListVPCsWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ Iterable<VPC> vpcs = api.vpcApi().list(TEST_REGION, paginationOptions(pageNumber(2)));
+ assertTrue(isEmpty(vpcs));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeVpcs", ImmutableMap.of("RegionId", TEST_REGION), 2);
+ }
+
+ public void testCreateVPC() throws InterruptedException {
+ server.enqueue(jsonResponse("/vpc-create-res.json"));
+ VPCRequest vpcRequest = api.vpcApi().create(TEST_REGION);
+ assertEquals(vpcRequest, objectFromResource("/vpc-create-res.json", VPCRequest.class));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "CreateVpc", ImmutableMap.of("RegionId", TEST_REGION));
+ }
+
+ public void testDeleteVPC() throws InterruptedException {
+ server.enqueue(jsonResponse("/vpc-delete-res.json"));
+ Request delete = api.vpcApi().delete(TEST_REGION, "vpc-123456789");
+ assertEquals(delete, objectFromResource("/vpc-delete-res.json", Request.class));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "DeleteVpc", ImmutableMap.of("RegionId", TEST_REGION, "VpcId", "vpc-123456789"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiLiveTest.java
new file mode 100644
index 0000000..c7abc40
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiLiveTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.features;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiLiveTest;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.VSwitchRequest;
+import org.jclouds.aliyun.ecs.domain.options.CreateVSwitchOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions;
+import org.jclouds.aliyun.ecs.features.VSwitchApi;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.jclouds.aliyun.ecs.domain.options.PaginationOptions.Builder.pageSize;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.util.Strings.isNullOrEmpty;
+
+@Test(groups = "live", testName = "VSwitchApiLiveTest")
+public class VSwitchApiLiveTest extends BaseECSComputeServiceApiLiveTest {
+
+ public static final String VSWITCH_NAME = "jclouds-vswitch";
+ public static final String DEFAULT_CIDR_BLOCK = "172.16.1.0/24";
+ private String vpcId;
+ private String vSwitchId;
+
+ @BeforeClass
+ public void setUp() {
+ VPCRequest preRequisite = api.vpcApi().create(TEST_REGION);
+ vpcId = preRequisite.getVpcId();
+ VSwitchRequest vpcRequest = api().create(
+ TEST_ZONE,
+ DEFAULT_CIDR_BLOCK,
+ vpcId,
+ CreateVSwitchOptions.Builder.vSwitchName(VSWITCH_NAME));
+ assertNotNull(vpcRequest.getRequestId());
+ assertNotNull(vpcRequest.getVSwitchId());
+ vSwitchId = vpcRequest.getVSwitchId();
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void tearDown() {
+ if (vSwitchId != null) {
+ assertNotNull(api().delete(TEST_REGION, vSwitchId));
+ }
+ if (vpcId != null) {
+ assertNotNull(api.vpcApi().delete(TEST_REGION, vpcId));
+ }
+ }
+
+ public void testList() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(Iterables.all(api().list(TEST_REGION).concat(), new Predicate<VSwitch>() {
+ @Override
+ public boolean apply(VSwitch input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.id());
+ }
+ }), "All vSwitches must have at least the 'id' field populated");
+ assertTrue(found.get() > 0, "Expected some vSwitch to be returned");
+ }
+
+ public void testListWithOptions() {
+ final AtomicInteger found = new AtomicInteger(0);
+ assertTrue(api().list(TEST_REGION, ListVSwitchesOptions.Builder.vSwitchId(vSwitchId)
+ .paginationOptions(pageSize(50)))
+ .firstMatch(new Predicate<VSwitch>() {
+ @Override
+ public boolean apply(VSwitch input) {
+ found.incrementAndGet();
+ return !isNullOrEmpty(input.id());
+ }
+ }).isPresent(), "All vSwitches must have at least the 'id' field populated");
+ assertTrue(found.get() > 0, "Expected some vSwitch to be returned");
+ }
+
+ private VSwitchApi api() {
+ return api.vSwitchApi();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiMockTest.java
new file mode 100644
index 0000000..b80111d
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/features/VSwitchApiMockTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.features;
+
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.aliyun.ecs.compute.internal.BaseECSComputeServiceApiMockTest;
+import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.VSwitchRequest;
+import org.jclouds.collect.IterableWithMarker;
+import org.testng.annotations.Test;
+
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions.Builder.paginationOptions;
+import static org.jclouds.aliyun.ecs.domain.options.PaginationOptions.Builder.pageNumber;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+@Test(groups = "unit", testName = "VSwitchApiMockTest", singleThreaded = true)
+public class VSwitchApiMockTest extends BaseECSComputeServiceApiMockTest {
+
+ public void testListVSwitches() throws InterruptedException {
+ server.enqueue(jsonResponse("/vswitches-first.json"));
+ server.enqueue(jsonResponse("/vswitches-last.json"));
+ Iterable<VSwitch> vSwitches = api.vSwitchApi().list(TEST_REGION).concat();
+ assertEquals(size(vSwitches), 2); // Force the PagedIterable to advance
+ assertEquals(server.getRequestCount(), 2);
+ assertSent(server, "GET", "DescribeVSwitches", ImmutableMap.of("RegionId", TEST_REGION));
+ assertSent(server, "GET", "DescribeVSwitches", ImmutableMap.of("RegionId", TEST_REGION), 2);
+ }
+
+ public void testListVSwitchesReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ Iterable<VSwitch> vSwitches = api.vSwitchApi().list(TEST_REGION).concat();
+ assertTrue(isEmpty(vSwitches));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeVSwitches", ImmutableMap.of("RegionId", TEST_REGION));
+ }
+
+ public void testListVSwitchesWithOptions() throws InterruptedException {
+ server.enqueue(jsonResponse("/vswitches-first.json"));
+ IterableWithMarker<VSwitch> vSwitches = api.vSwitchApi().list(TEST_REGION, paginationOptions(pageNumber(1).pageSize(5)));
+ assertEquals(size(vSwitches), 1);
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeVSwitches", ImmutableMap.of("RegionId", TEST_REGION), 1);
+ }
+
+ public void testListVSwitchesWithOptionsReturns404() throws InterruptedException {
+ server.enqueue(response404());
+ IterableWithMarker<VSwitch> vSwitches = api.vSwitchApi().list(TEST_REGION, paginationOptions(pageNumber(2)));
+ assertTrue(isEmpty(vSwitches));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "GET", "DescribeVSwitches", ImmutableMap.of("RegionId", TEST_REGION), 2);
+ }
+
+ public void testCreateVSwitch() throws InterruptedException {
+ server.enqueue(jsonResponse("/vswitch-create-res.json"));
+ VSwitchRequest vSwitchRequest = api.vSwitchApi().create(TEST_ZONE, "192.168.1.0/24", "vsw-25naue4gz");
+ assertEquals(vSwitchRequest, objectFromResource("/vswitch-create-res.json", VSwitchRequest.class));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "CreateVSwitch", ImmutableMap.of("ZoneId", TEST_ZONE, "CidrBlock", "192.168.1.0/24", "VpcId", "vsw-25naue4gz"));
+ }
+
+ public void testDeletVSwitch() throws InterruptedException {
+ server.enqueue(jsonResponse("/vswitch-delete-res.json"));
+ Request delete = api.vSwitchApi().delete(TEST_REGION, "vsw-123456789");
+ assertEquals(delete, objectFromResource("/vswitch-delete-res.json", Request.class));
+ assertEquals(server.getRequestCount(), 1);
+ assertSent(server, "POST", "DeleteVSwitch", ImmutableMap.of("RegionId", TEST_REGION, "VSwitchId", "vsw-123456789"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImageTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImageTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImageTest.java
new file mode 100644
index 0000000..c9cf1ab
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImageTest.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.jclouds.aliyun.ecs.domain.DiskDeviceMapping;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
+import org.jclouds.aliyun.ecs.domain.regionscoped.ImageInRegion;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import javax.xml.bind.DatatypeConverter;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import static org.jclouds.aliyun.ecs.domain.Image.Status.AVAILABLE;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertTrue;
+
+@Test(groups = "unit", testName = "ImageInRegionToImageTest")
+public class ImageInRegionToImageTest {
+
+ private final Location region = new LocationBuilder()
+ .id(Regions.EU_CENTRAL_1.getName())
+ .description(Regions.EU_CENTRAL_1.getDescription())
+ .scope(LocationScope.REGION).build();
+ private final Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet.of(region));
+
+ private ImageInRegionToImage imageInRegionToImage;
+
+ @BeforeMethod
+ public void setUp() {
+ imageInRegionToImage = new ImageInRegionToImage(locations);
+ }
+
+ @Test
+ public void testOsImageToImage() {
+ final org.jclouds.aliyun.ecs.domain.Image ecsImage = org.jclouds.aliyun.ecs.domain.Image.builder()
+ .id("centos_6_09_64_20G_alibase_20180326.vhd")
+ .description("")
+ .productCode("")
+ .osType("linux")
+ .architecture("x86_64")
+ .osName("CentOS 6.9 64位")
+ .imageOwnerAlias("system")
+ .progress("100%")
+ .isSupportCloudinit(true)
+ .usage("instance")
+ .creationTime(parseDate("2018-05-10T12:40:55Z"))
+ .imageVersion("")
+ .status(AVAILABLE)
+ .name("centos_6_09_64_20G_alibase_20180326.vhd")
+ .isSupportIoOptimizeds(true)
+ .isCopied(false)
+ .isSubscribed(false)
+ .isSelfShared(false)
+ .platform("CentOS")
+ .size(20)
+ .diskDeviceMappings(ImmutableMap.<String, List<DiskDeviceMapping>>of())
+ .tags(ImmutableMap.<String, List<Tag>>of())
+ .build();
+
+ final Image image = imageInRegionToImage.apply(ImageInRegion.create(Regions.EU_CENTRAL_1.getName(), ecsImage));
+ assertEquals(ecsImage.id(), image.getProviderId());
+ assertEquals(ecsImage.name(), image.getName());
+ assertEquals(Image.Status.AVAILABLE, image.getStatus());
+ final org.jclouds.compute.domain.OperatingSystem operatingSystem = image.getOperatingSystem();
+
+ assertEquals(ecsImage.osName(), operatingSystem.getName());
+ assertEquals(ecsImage.description(), operatingSystem.getDescription());
+ assertTrue(operatingSystem.is64Bit());
+ assertEquals(region, image.getLocation());
+ }
+
+ @Test
+ public void testOsImageFromOtherOSMapToImage() {
+ final org.jclouds.aliyun.ecs.domain.Image ecsImage = org.jclouds.aliyun.ecs.domain.Image.builder()
+ .id("alinux_17_01_64_20G_cloudinit_20171222.vhd")
+ .description("")
+ .productCode("")
+ .osType("linux")
+ .architecture("x86_64")
+ .osName("Aliyun Linux 17.1 64位")
+ .imageOwnerAlias("system")
+ .progress("100%")
+ .isSupportCloudinit(true)
+ .usage("instance")
+ .creationTime(parseDate("2017-12-22T05:56:16Z"))
+ .imageVersion("")
+ .status(AVAILABLE)
+ .name("alinux_17_01_64_20G_cloudinit_20171222.vhd")
+ .isSupportIoOptimizeds(true)
+ .isCopied(false)
+ .isSubscribed(false)
+ .isSelfShared(false)
+ .platform("Aliyun")
+ .size(20)
+ .diskDeviceMappings(ImmutableMap.<String, List<DiskDeviceMapping>>of())
+ .tags(ImmutableMap.<String, List<Tag>>of())
+ .build();
+
+ final Image image = imageInRegionToImage.apply(ImageInRegion.create(Regions.EU_CENTRAL_1.getName(), ecsImage));
+ assertEquals(ecsImage.id(), image.getProviderId());
+ assertEquals(ecsImage.name(), image.getName());
+ assertEquals(Image.Status.AVAILABLE, image.getStatus());
+ final org.jclouds.compute.domain.OperatingSystem operatingSystem = image.getOperatingSystem();
+
+ assertEquals(ecsImage.osName(), operatingSystem.getName());
+ assertEquals(ecsImage.description(), operatingSystem.getDescription());
+ assertTrue(operatingSystem.is64Bit());
+ assertEquals(region, image.getLocation());
+ }
+
+ Date parseDate(final String dateString) {
+ return DatatypeConverter.parseDateTime(dateString).getTime();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatusTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatusTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatusTest.java
new file mode 100644
index 0000000..62f22e5
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatusTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+
+/**
+ * Unit tests for the {@link InstanceStatusToStatus} class.
+ */
+@Test(groups = "unit", testName = "InstanceStatusToStatusTest")
+public class InstanceStatusToStatusTest {
+ private InstanceStatusToStatus function;
+
+ @BeforeMethod
+ public void setup() {
+ function = new InstanceStatusToStatus();
+ }
+
+ public void testStatusRunningToStatusRunning() {
+ NodeMetadata.Status status = function.apply(Instance.Status.RUNNING);
+ assertEquals(status, NodeMetadata.Status.RUNNING);
+ }
+
+ public void testStatusStartingToStatusPending() {
+ NodeMetadata.Status status = function.apply(Instance.Status.STARTING);
+ assertEquals(status, NodeMetadata.Status.PENDING);
+ }
+
+ public void testStatusStoppingToStatusPending() {
+ NodeMetadata.Status status = function.apply(Instance.Status.STOPPING);
+ assertEquals(status, NodeMetadata.Status.PENDING);
+ }
+
+ public void testStatusStoppedToStatusSuspended() {
+ NodeMetadata.Status status = function.apply(Instance.Status.STOPPED);
+ assertEquals(status, NodeMetadata.Status.SUSPENDED);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToHardwareTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToHardwareTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToHardwareTest.java
new file mode 100644
index 0000000..910703c
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToHardwareTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import org.jclouds.aliyun.ecs.domain.InstanceType;
+import org.jclouds.compute.domain.Hardware;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import static org.testng.AssertJUnit.assertEquals;
+
+@Test(groups = "unit", testName = "InstanceToHardwareTest")
+public class InstanceToHardwareTest {
+
+ private InstanceTypeToHardware instanceTypeToHardware;
+
+ @BeforeMethod
+ public void setUp() {
+ instanceTypeToHardware = new InstanceTypeToHardware();
+ }
+
+ @Test
+ public void testApplyServer() {
+ final InstanceType instanceType = InstanceType.builder()
+ .id("ecs.t1.small")
+ .cpuCoreCount(1)
+ .instanceTypeFamily("ecs.t1")
+ .eniQuantity(1)
+ .memorySize(1.0)
+ .gpuAmount(0d)
+ .localStorageCategory("")
+ .gpuSpec("")
+ .build();
+ applyAndAssert(instanceType);
+ }
+
+ private void applyAndAssert(InstanceType instanceType) {
+ final Hardware hardware = instanceTypeToHardware.apply(instanceType);
+ assertEquals(instanceType.memorySize().intValue() * 1024, hardware.getRam());
+ assertEquals(instanceType.id(), hardware.getId());
+ assertEquals(instanceType.id(), hardware.getProviderId());
+ assertEquals(instanceType.id(), hardware.getName());
+ assertEquals(instanceType.cpuCoreCount().intValue(), hardware.getProcessors().size());
+ assertEquals(Double.valueOf(instanceType.cpuCoreCount().intValue()), hardware.getProcessors().get(0).getCores());
+ }
+
+}
[3/7] jclouds-labs git commit: [JCLOUDS-1430] Aliyun ECS
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java
new file mode 100644
index 0000000..2cefe83
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadataTest.java
@@ -0,0 +1,249 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Guice;
+import org.jclouds.aliyun.ecs.domain.DedicatedHostAttribute;
+import org.jclouds.aliyun.ecs.domain.EipAddress;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.NetworkInterface;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.VpcAttributes;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+@Test(groups = "unit", testName = "InstanceToNodeMetadataTest")
+public class InstanceToNodeMetadataTest {
+
+ private InstanceToNodeMetadata instanceToNodeMetadata;
+ private Image image;
+ private Hardware hardware;
+ private Location location;
+ private Instance instance;
+ private OperatingSystem os;
+ private Map<String, List<Tag>> tags;
+
+ private String imageId = "centos_6_09_64_20G_alibase_20180326.vhd";
+ private String hardwareId = "ecs.t1.xsmall";
+ private String regionId = Regions.EU_CENTRAL_1.getName();
+
+ @BeforeMethod
+ public void setUp() {
+
+ location = new LocationBuilder().id(regionId)
+ .description(Regions.EU_CENTRAL_1.getDescription())
+ .scope(LocationScope.PROVIDER)
+ .build();
+ Supplier<Set<? extends Location>> locations = new Supplier<Set<? extends Location>>() {
+ @Override
+ public Set<? extends Location> get() {
+ return ImmutableSet.of(location);
+ }
+ };
+
+ GroupNamingConvention.Factory namingConvention = Guice.createInjector().getInstance(GroupNamingConvention.Factory.class);
+
+ hardware = new HardwareBuilder()
+ .ids(hardwareId)
+ .name(hardwareId)
+ .ram(1024)
+ .processor(new Processor(1, 1d))
+ .location(location)
+ .build();
+
+ os = OperatingSystem.builder()
+ .description("CentOS 6.9 64bit")
+ .family(OsFamily.CENTOS)
+ .version("6.9")
+ .is64Bit(true)
+ .build();
+
+ image = new ImageBuilder()
+ .id(RegionAndId.slashEncodeRegionAndId(regionId, imageId))
+ .providerId(imageId)
+ .name("CentOS 6.9 64位")
+ .description("")
+ .operatingSystem(os)
+ .status(Image.Status.AVAILABLE)
+ .build();
+
+ tags = ImmutableMap.<String, List<Tag>>of("Tag", ImmutableList.of(Tag.create("hello", "")));
+
+ instance = Instance.builder()
+ .id("serverId")
+ .name("instanceName")
+ .regionId(regionId)
+ .imageId(imageId)
+ .instanceType(hardwareId)
+ .instanceTypeFamily("linux")
+ .vlanId("vlanId")
+ .eipAddress(EipAddress.create("ipAddress", "allocationId", EipAddress.InternetChargeType.ECS_INSTANCE))
+ .internetMaxBandwidthIn(1)
+ .zoneId("zoneId")
+ .internetChargeType(Instance.InternetChargeType.PAY_BY_TRAFFIC)
+ .spotStrategy("spotStrategy")
+ .stoppedMode("stoppedMode")
+ .serialNumber("serialNumber")
+ .ioOptimized(true)
+ .memory(1024)
+ .cpu(1)
+ .vpcAttributes(VpcAttributes.create("natIpAddress", ImmutableMap.<String, List<String>>of(), "vSwitchId", "vpcId"))
+ .internetMaxBandwidthOut(1)
+ .deviceAvailable(true)
+ .saleCycle("saleCycle")
+ .spotPriceLimit(1d)
+ .autoReleaseTime("")
+ .startTime(new SimpleDateFormatDateService().iso8601DateParse("2014-03-22T07:16:45.784120972Z"))
+ .description("desc")
+ .resourceGroupId("resourceGroupId")
+ .osType("osType")
+ .osName("osName")
+ .instanceNetworkType("instanceNetworkType")
+ .hostname("hostname")
+ .creationTime(new SimpleDateFormatDateService().iso8601DateParse("2014-03-22T05:16:45.784120972Z"))
+ .status(Instance.Status.RUNNING)
+ .clusterId("clusterId")
+ .recyclable(false)
+ .gpuSpec("")
+ .dedicatedHostAttribute(DedicatedHostAttribute.create("id", "name"))
+ .instanceChargeType("instanceChargeType")
+ .gpuAmount(1)
+ .expiredTime(new SimpleDateFormatDateService().iso8601DateParse("2014-03-22T09:16:45.784120972Z"))
+ .innerIpAddress(ImmutableMap.<String, List<String>>of("IpAddress", ImmutableList.of("192.168.0.1", "192.168.0.2")))
+ .publicIpAddress(ImmutableMap.<String, List<String>>of("IpAddress", ImmutableList.of("47.254.152.220", "47.254.153.230")))
+ .securityGroupIds(ImmutableMap.<String, List<String>>of())
+ .networkInterfaces(ImmutableMap.<String, List<NetworkInterface>>of())
+ .operationLocks(ImmutableMap.<String, List<String>>of())
+ .tags(tags)
+ .build();
+
+ Supplier<Map<String, ? extends Image>> images = new Supplier<Map<String, ? extends Image>>() {
+ @Override
+ public Map<String, ? extends Image> get() {
+ return ImmutableMap.of(imageId, image);
+ }
+ };
+
+ Supplier<Map<String, ? extends Hardware>> hardwares = new Supplier<Map<String, ? extends Hardware>>() {
+ @Override
+ public Map<String, ? extends Hardware> get() {
+ return ImmutableMap.of(hardwareId, hardware);
+ }
+ };
+
+ instanceToNodeMetadata = new InstanceToNodeMetadata(images, hardwares, locations,
+ new InstanceStatusToStatus(), namingConvention);
+ }
+
+ @Test
+ public void testInstanceToNodeMetadata() {
+ NodeMetadata node = instanceToNodeMetadata.apply(instance);
+
+ List<String> privateIpAddresses = instance.innerIpAddress().entrySet().iterator().next().getValue();
+ List<String> publicIpAddresses = instance.publicIpAddress().entrySet().iterator().next().getValue();
+
+ assertNotNull(node);
+ assertEquals(node.getProviderId(), instance.id());
+ assertEquals(node.getName(), instance.name());
+ assertEquals(node.getHostname(), instance.hostname());
+ assertEquals(node.getGroup(), instance.name());
+ assertEquals(node.getHardware(), hardware);
+ assertEquals(node.getImageId(), RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+ assertEquals(node.getOperatingSystem(), os);
+ assertEquals(node.getLocation(), location);
+ assertEquals(node.getImageId(), RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+ assertEquals(node.getStatus(), NodeMetadata.Status.RUNNING);
+ assertEquals(node.getPrivateAddresses(), privateIpAddresses);
+ assertEquals(node.getPublicAddresses(), publicIpAddresses);
+ assertEquals(node.getTags(), ImmutableSet.of("hello"));
+ }
+
+ @Test
+ public void testInstanceWithInvalidHardwareToNodeMetadata() {
+ Instance instanceWithoutValidHardwareId = instance.toBuilder().instanceType("not.valid").build();
+ NodeMetadata node = instanceToNodeMetadata.apply(instanceWithoutValidHardwareId);
+
+ List<String> privateIpAddresses = instanceWithoutValidHardwareId.innerIpAddress().entrySet().iterator().next().getValue();
+ List<String> publicIpAddresses = instanceWithoutValidHardwareId.publicIpAddress().entrySet().iterator().next().getValue();
+
+ assertNotNull(node);
+ assertEquals(node.getProviderId(), instanceWithoutValidHardwareId.id());
+ assertEquals(node.getName(), instanceWithoutValidHardwareId.name());
+ assertEquals(node.getHostname(), instanceWithoutValidHardwareId.hostname());
+ assertEquals(node.getGroup(), instanceWithoutValidHardwareId.name());
+ assertEquals(node.getHardware(), null);
+ assertEquals(node.getImageId(), RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+ assertEquals(node.getOperatingSystem(), os);
+ assertEquals(node.getLocation(), location);
+ assertEquals(node.getImageId(), RegionAndId.slashEncodeRegionAndId(regionId, imageId));
+ assertEquals(node.getStatus(), NodeMetadata.Status.RUNNING);
+ assertEquals(node.getPrivateAddresses(), privateIpAddresses);
+ assertEquals(node.getPublicAddresses(), publicIpAddresses);
+ assertEquals(node.getTags(), ImmutableSet.of("hello"));
+ }
+
+ @Test
+ public void testInstanceWithInvalidImageToNodeMetadata() {
+ Instance instanceWithoutValidHardwareId = instance.toBuilder().imageId("not.valid").build();
+ NodeMetadata node = instanceToNodeMetadata.apply(instanceWithoutValidHardwareId);
+
+ List<String> privateIpAddresses = instanceWithoutValidHardwareId.innerIpAddress().entrySet().iterator().next().getValue();
+ List<String> publicIpAddresses = instanceWithoutValidHardwareId.publicIpAddress().entrySet().iterator().next().getValue();
+
+ assertNotNull(node);
+ assertEquals(node.getProviderId(), instanceWithoutValidHardwareId.id());
+ assertEquals(node.getName(), instanceWithoutValidHardwareId.name());
+ assertEquals(node.getHostname(), instanceWithoutValidHardwareId.hostname());
+ assertEquals(node.getGroup(), instanceWithoutValidHardwareId.name());
+ assertEquals(node.getHardware(), hardware);
+ assertEquals(node.getImageId(), null);
+ assertEquals(node.getOperatingSystem(), null);
+ assertEquals(node.getImageId(), null);
+ assertEquals(node.getLocation(), location);
+ assertEquals(node.getStatus(), NodeMetadata.Status.RUNNING);
+ assertEquals(node.getPrivateAddresses(), privateIpAddresses);
+ assertEquals(node.getPublicAddresses(), publicIpAddresses);
+ assertEquals(node.getTags(), ImmutableSet.of("hello"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
index f7b9526..c18d2b6 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiLiveTest.java
@@ -16,19 +16,33 @@
*/
package org.jclouds.aliyun.ecs.compute.internal;
+import com.google.common.base.Predicate;
import com.google.inject.Injector;
+import com.google.inject.Key;
import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Names;
import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.apis.BaseApiLiveTest;
import org.jclouds.compute.config.ComputeServiceProperties;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+
public class BaseECSComputeServiceApiLiveTest extends BaseApiLiveTest<ECSComputeServiceApi> {
+ protected static final String TEST_REGION = System.getProperty("test.alibaba-ecs.region", Regions.EU_CENTRAL_1.getName());
+ protected static final String TEST_ZONE = System.getProperty("test.alibaba-ecs.zone", TEST_REGION + "a");
+
+ protected Predicate<String> instanceRunningPredicate;
+ protected Predicate<String> instanceSuspendedPredicate;
+
public BaseECSComputeServiceApiLiveTest() {
- provider = "aliyun-ecs";
+ provider = "alibaba-ecs";
}
@Override
@@ -43,6 +57,12 @@ public class BaseECSComputeServiceApiLiveTest extends BaseApiLiveTest<ECSCompute
@Override
protected ECSComputeServiceApi create(Properties props, Iterable<Module> modules) {
Injector injector = newBuilder().modules(modules).overrides(props).buildInjector();
+
+ instanceRunningPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>() {
+ }, Names.named(TIMEOUT_NODE_RUNNING)));
+ instanceSuspendedPredicate = injector.getInstance(Key.get(new TypeLiteral<Predicate<String>>() {
+ }, Names.named(TIMEOUT_NODE_SUSPENDED)));
+
return injector.getInstance(ECSComputeServiceApi.class);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
index dd3938d..e25b08f 100644
--- a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/internal/BaseECSComputeServiceApiMockTest.java
@@ -29,6 +29,7 @@ import com.squareup.okhttp.mockwebserver.RecordedRequest;
import org.jclouds.ContextBuilder;
import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
import org.jclouds.aliyun.ecs.ECSComputeServiceProviderMetadata;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
import org.jclouds.concurrent.config.ExecutorServiceModule;
import org.jclouds.json.Json;
import org.jclouds.rest.ApiContext;
@@ -48,6 +49,8 @@ import static org.testng.Assert.assertTrue;
public class BaseECSComputeServiceApiMockTest {
private static final String DEFAULT_ENDPOINT = new ECSComputeServiceProviderMetadata().getEndpoint();
+ protected static final String TEST_REGION = Regions.EU_CENTRAL_1.getName();
+ protected static final String TEST_ZONE = TEST_REGION + "a";
private final Set<Module> modules = ImmutableSet.<Module>of(new ExecutorServiceModule(newDirectExecutorService()));
protected MockWebServer server;
@@ -59,7 +62,7 @@ public class BaseECSComputeServiceApiMockTest {
public void start() throws IOException {
server = new MockWebServer();
server.play();
- ctx = ContextBuilder.newBuilder("aliyun-ecs").credentials("user", "password").endpoint(url("")).modules(modules)
+ ctx = ContextBuilder.newBuilder("alibaba-ecs").credentials("user", "password").endpoint(url("")).modules(modules)
.overrides(overrides()).build();
json = ctx.utils().injector().getInstance(Json.class);
api = ctx.getApi();
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java
new file mode 100644
index 0000000..4bff6d3
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodesTest.java
@@ -0,0 +1,395 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.strategy;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import org.easymock.EasyMock;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.compute.options.ECSServiceTemplateOptions;
+import org.jclouds.aliyun.ecs.domain.IpProtocol;
+import org.jclouds.aliyun.ecs.domain.KeyPairRequest;
+import org.jclouds.aliyun.ecs.domain.Permission;
+import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.ResourceInfo;
+import org.jclouds.aliyun.ecs.domain.ResourceType;
+import org.jclouds.aliyun.ecs.domain.SecurityGroup;
+import org.jclouds.aliyun.ecs.domain.SecurityGroupRequest;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.VSwitchRequest;
+import org.jclouds.aliyun.ecs.domain.Zone;
+import org.jclouds.aliyun.ecs.domain.internal.PaginatedCollection;
+import org.jclouds.aliyun.ecs.domain.internal.Regions;
+import org.jclouds.aliyun.ecs.domain.options.CreateSecurityGroupOptions;
+import org.jclouds.aliyun.ecs.domain.options.CreateVPCOptions;
+import org.jclouds.aliyun.ecs.domain.options.CreateVSwitchOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions;
+import org.jclouds.aliyun.ecs.domain.options.TagOptions;
+import org.jclouds.aliyun.ecs.features.RegionAndZoneApi;
+import org.jclouds.aliyun.ecs.features.SecurityGroupApi;
+import org.jclouds.aliyun.ecs.features.SshKeyPairApi;
+import org.jclouds.aliyun.ecs.features.TagApi;
+import org.jclouds.aliyun.ecs.features.VPCApi;
+import org.jclouds.aliyun.ecs.features.VSwitchApi;
+import org.jclouds.collect.IterableWithMarkers;
+import org.jclouds.collect.PagedIterables;
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
+import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.domain.Location;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import static org.easymock.EasyMock.anyString;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMockSupport.injectMocks;
+import static org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes.DEFAULT_CIDR_BLOCK;
+import static org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes.DEFAULT_DESCRIPTION_SUFFIX;
+import static org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes.VSWITCH_PREFIX;
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ *
+ * User can specify security group and vSwitch.
+ * 1. security group and vSwitch
+ * 2. only security group -> impossible to determine which vSwitch the user wants to use or create
+ * 3. only vswitch ID -> create a securitygroup in the same vpc
+ * 4. none of them -> create vpc, vswitch and securitygroup
+ *
+ * Case 1 is tested with testExecuteWithSecurityGroupsVSwitchId
+ * Case 2 testExecuteOnlySecurityGroup
+ * Case 3 is tested with testExecuteOnlyVSwitchId
+ * Case 4 is tested with testExecuteNoSecurityGroupsVSwitchId
+ */
+@Test(groups = "unit", testName = "CreateResourcesThenCreateNodesTest")
+public class CreateResourcesThenCreateNodesTest {
+
+ private CreateResourcesThenCreateNodes createResourcesThenCreateNodes;
+ private SecurityGroupApi securityGroupApi;
+ private VSwitchApi vSwitchApi;
+ private TagApi tagApi;
+ private SshKeyPairApi sshKeyPairApi;
+ private VPCApi vpcApi;
+ private RegionAndZoneApi regionAndZoneApi;
+ private ECSComputeServiceApi api;
+ private Template template;
+ private ECSServiceTemplateOptions templateOptions;
+ private CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy;
+ private ListNodesStrategy listNodesStrategy;
+ private GroupNamingConvention.Factory factory;
+ private GroupNamingConvention namingConvention;
+ private ListeningExecutorService userExecutor;
+ private CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory;
+ private ComputeServiceConstants.Timeouts timeouts;
+ private Location location;
+ private String regionId;
+ private SecurityGroup securityGroup;
+ private Permission permission;
+ private VSwitch vswitch;
+ private Zone zone;
+
+ @BeforeMethod
+ public void setUp() {
+ securityGroupApi = EasyMock.createMock(SecurityGroupApi.class);
+ vSwitchApi = EasyMock.createMock(VSwitchApi.class);
+ tagApi = EasyMock.createMock(TagApi.class);
+ sshKeyPairApi = EasyMock.createMock(SshKeyPairApi.class);
+ vpcApi = EasyMock.createMock(VPCApi.class);
+ regionAndZoneApi = EasyMock.createMock(RegionAndZoneApi.class);
+ api = EasyMock.createMock(ECSComputeServiceApi.class);
+ template = EasyMock.createNiceMock(Template.class);
+ addNodeWithGroupStrategy = EasyMock.createNiceMock(CreateNodeWithGroupEncodedIntoName.class);
+ listNodesStrategy = EasyMock.createNiceMock(ListNodesStrategy.class);
+ factory = EasyMock.createNiceMock(GroupNamingConvention.Factory.class);
+ namingConvention = EasyMock.createNiceMock(GroupNamingConvention.class);
+
+ userExecutor = EasyMock.createNiceMock(ListeningExecutorService.class);
+ customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory = EasyMock
+ .createNiceMock(CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory.class);
+ location = createNiceMock(Location.class);
+ templateOptions = new ECSServiceTemplateOptions();
+ regionId = Regions.EU_CENTRAL_1.getName();
+
+ timeouts = new ComputeServiceConstants.Timeouts();
+
+ createResourcesThenCreateNodes = new CreateResourcesThenCreateNodes(addNodeWithGroupStrategy,
+ listNodesStrategy, factory, userExecutor,
+ customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory, api);
+
+ permission = Permission.create(
+ "",
+ "",
+ "",
+ Permission.NicType.INTERNET,
+ "",
+ "",
+ "",
+ Permission.Direction.ALL,
+ "",
+ IpProtocol.ALL,
+ "",
+ Permission.Policy.ACCEPT,
+ new Date(),
+ "",
+ "",
+ ""
+ );
+
+ zone = Zone.create("id",
+ "localName",
+ ImmutableMap.<String, List<Object>>of(),
+ ImmutableMap.<String, List<String>>of(),
+ ImmutableMap.<String, List<String>>of(),
+ ImmutableMap.<String, List<ResourceInfo>>of(),
+ ImmutableMap.<String, List<String>>of(),
+ ImmutableMap.<String, List<String>>of(),
+ ImmutableMap.<String, List<String>>of()
+ );
+
+ injectMocks(api);
+ injectMocks(template);
+ injectMocks(securityGroupApi);
+ injectMocks(vSwitchApi);
+ injectMocks(tagApi);
+ injectMocks(sshKeyPairApi);
+ injectMocks(vpcApi);
+ injectMocks(regionAndZoneApi);
+
+ expect(template.getLocation()).andReturn(location).anyTimes();
+ expect(location.getId()).andReturn(regionId).anyTimes();
+
+ expect(api.securityGroupApi()).andReturn(securityGroupApi).anyTimes();
+ expect(api.vSwitchApi()).andReturn(vSwitchApi).anyTimes();
+ expect(api.tagApi()).andReturn(tagApi).anyTimes();
+ expect(api.sshKeyPairApi()).andReturn(sshKeyPairApi).anyTimes();
+ expect(api.vpcApi()).andReturn(vpcApi).anyTimes();
+ expect(api.regionAndZoneApi()).andReturn(regionAndZoneApi).anyTimes();
+ }
+
+
+ @Test
+ public void testExecuteWithSecurityGroupsVSwitchId() {
+ String vpcId = "vpc-1";
+ String vSwitchId = "vs-1";
+ String securityGroupId = "sg-1";
+ securityGroup = createSecurityGroup(securityGroupId, vpcId);
+ vswitch = createVSwitch(vSwitchId, vpcId);
+
+ templateOptions.vSwitchId(vSwitchId).securityGroups(securityGroupId);
+
+ expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+ expect(securityGroupApi.list(regionId))
+ .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(securityGroup))));
+
+ expect(securityGroupApi.get(regionId, securityGroupId))
+ .andReturn(Lists.newArrayList(permission));
+
+ // found VSwitch specified by user in VPC_PREFIX
+ expect(vSwitchApi.list(regionId, ListVSwitchesOptions.Builder.vSwitchId(vSwitchId).vpcId(vpcId)))
+ .andReturn(new PaginatedCollection(ImmutableMap.<String, Iterable<VSwitch>>of("VSwitch", Lists.<VSwitch> newArrayList(vswitch)), 1, 1, 1, regionId, "requestId"));
+
+ expect(factory.create()).andReturn(namingConvention).anyTimes();
+ expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+ expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+ expect(securityGroupApi.create(regionId, CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+ .andReturn(new SecurityGroupRequest("requestId", securityGroupId)).anyTimes();
+ expect(securityGroupApi.addInboundRule(regionId, securityGroupId, IpProtocol.TCP, "22/22", "0.0.0.0/0"))
+ .andReturn(new Request("requestId")).anyTimes();
+ expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+ TagOptions.Builder.tag(1, Tag.DEFAULT_OWNER_KEY, Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+ ).andReturn(new Request("requestId")).anyTimes();
+ expect(sshKeyPairApi.create(regionId, "prefix"))
+ .andReturn(new KeyPairRequest("requestId", "name", "fingerPrint", "body")).anyTimes();
+
+ replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, regionAndZoneApi, api, factory, namingConvention, template, location);
+
+ executeAndAssert(vSwitchId, securityGroupId);
+ }
+
+ @Test(dependsOnMethods = "testExecuteWithSecurityGroupsVSwitchId")
+ public void testExecuteNoSecurityGroupsNoVSwitchId() {
+ String vpcId = "vpc-1";
+ String vSwitchId = "vs-1";
+ String securityGroupId = "sg-1";
+
+ vswitch = createVSwitch(vSwitchId, vpcId);
+
+ expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+ expect(securityGroupApi.list(regionId))
+ .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.<SecurityGroup>newArrayList())));
+
+ expect(vSwitchApi.list(regionId))
+ .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.<VSwitch>newArrayList())));
+
+ expect(regionAndZoneApi.describeZones(regionId)).andReturn(ImmutableList.of(zone));
+ expect(vpcApi.create(regionId, CreateVPCOptions.Builder.vpcName(anyString()).description(anyString()))).andReturn(new VPCRequest("reqId", "routeId", "vRoutId", vpcId));
+
+ String vSwitchName = String.format("%s-%s", VSWITCH_PREFIX, "group");
+ String vSwitchDescription = String.format("%s - %s", vSwitchName, DEFAULT_DESCRIPTION_SUFFIX);
+ expect(vSwitchApi.create(zone.id(), DEFAULT_CIDR_BLOCK, vpcId,
+ CreateVSwitchOptions.Builder.vSwitchName(vSwitchName).description(vSwitchDescription))).andReturn(new VSwitchRequest("reqId", vSwitchId));
+
+ expect(factory.create()).andReturn(namingConvention).anyTimes();
+ expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+ expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+ expect(securityGroupApi.create(regionId, CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+ .andReturn(new SecurityGroupRequest("requestId", securityGroupId)).anyTimes();
+ expect(securityGroupApi.addInboundRule(regionId, securityGroupId, IpProtocol.TCP, "22/22", "0.0.0.0/0")).andReturn(new Request("requestId")).anyTimes();
+ expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+ TagOptions.Builder.tag(1, Tag.DEFAULT_OWNER_KEY, Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+ ).andReturn(new Request("requestId")).anyTimes();
+ expect(sshKeyPairApi.create(regionId, "prefix")).andReturn(new KeyPairRequest("requestId", "name", "fingerPrint", "body")).anyTimes();
+
+ replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, regionAndZoneApi, api, factory, namingConvention, template, location);
+
+ executeAndAssert(vSwitchId, securityGroupId);
+ }
+
+ @Test(dependsOnMethods = "testExecuteNoSecurityGroupsNoVSwitchId", expectedExceptions = IllegalStateException.class)
+ public void testExecuteOnlySecurityGroup() {
+ String vpcId = "vpc-2";
+ String vSwitchId = "";
+ String securityGroupId = "sg-2";
+ templateOptions.vSwitchId(vSwitchId).securityGroups(securityGroupId);
+ securityGroup = createSecurityGroup(securityGroupId, vpcId);
+ vswitch = createVSwitch(vSwitchId, vpcId);
+
+ expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+ expect(securityGroupApi.list(regionId))
+ .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.newArrayList(securityGroup))));
+
+ expect(securityGroupApi.get(regionId, securityGroupId))
+ .andReturn(Lists.newArrayList(permission));
+
+ // at least a VSwitch is available in regionId
+ expect(vSwitchApi.list(regionId, ListVSwitchesOptions.Builder.vpcId(vpcId)))
+ .andReturn(new PaginatedCollection(ImmutableMap.of("VSwitch", Lists.newArrayList(vswitch)), 1, 1, 1, regionId, "requestId"));
+
+ expect(factory.create()).andReturn(namingConvention).anyTimes();
+ expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+ expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+ expect(securityGroupApi.create(regionId, CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+ .andReturn(new SecurityGroupRequest("requestId", securityGroupId)).anyTimes();
+ expect(securityGroupApi.addInboundRule(regionId, securityGroupId, IpProtocol.TCP, "22/22", "0.0.0.0/0"))
+ .andReturn(new Request("requestId")).anyTimes();
+ expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+ TagOptions.Builder.tag(1, Tag.DEFAULT_OWNER_KEY, Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+ ).andReturn(new Request("requestId")).anyTimes();
+ expect(sshKeyPairApi.create(regionId, "prefix"))
+ .andReturn(new KeyPairRequest("requestId", "name", "fingerPrint", "body")).anyTimes();
+
+ replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, regionAndZoneApi, api, factory, namingConvention, template, location);
+
+ executeAndAssert(vSwitchId, securityGroupId);
+ }
+
+ @Test(dependsOnMethods = "testExecuteOnlySecurityGroup")
+ public void testExecuteOnlyVSwitchId() {
+ String vpcId = "vpc-3";
+ String vSwitchId = "vs-3";
+ String securityGroupId = "sg-3";
+ vswitch = createVSwitch(vSwitchId, vpcId);
+
+ templateOptions.vSwitchId(vSwitchId).securityGroups(securityGroupId);
+
+ expect(template.getOptions()).andReturn(templateOptions).anyTimes();
+
+ expect(securityGroupApi.list(regionId))
+ .andReturn(PagedIterables.onlyPage(IterableWithMarkers.from(Lists.<SecurityGroup> newArrayList())));
+
+ expect(securityGroupApi.get(regionId, securityGroupId))
+ .andReturn(Lists.newArrayList(permission));
+
+ // found VSwitch specified by user in VPC_PREFIX
+ expect(vSwitchApi.list(regionId, ListVSwitchesOptions.Builder.vSwitchId(vSwitchId)))
+ .andReturn(new PaginatedCollection(ImmutableMap.<String, Iterable<VSwitch>>of("VSwitch", Lists.<VSwitch> newArrayList(vswitch)), 1, 1, 1, regionId, "requestId"));
+
+ expect(factory.create()).andReturn(namingConvention).anyTimes();
+ expect(namingConvention.sharedNameForGroup(anyString())).andReturn("group").anyTimes();
+ expect(namingConvention.uniqueNameForGroup(anyString())).andReturn("prefix").anyTimes();
+
+ expect(securityGroupApi.create(regionId, CreateSecurityGroupOptions.Builder.securityGroupName("group").vpcId(vpcId)))
+ .andReturn(new SecurityGroupRequest("requestId", securityGroupId)).anyTimes();
+ expect(securityGroupApi.addInboundRule(regionId, securityGroupId, IpProtocol.TCP, "22/22", "0.0.0.0/0"))
+ .andReturn(new Request("requestId")).anyTimes();
+ expect(tagApi.add(regionId, securityGroupId, ResourceType.SECURITYGROUP,
+ TagOptions.Builder.tag(1, Tag.DEFAULT_OWNER_KEY, Tag.DEFAULT_OWNER_VALUE).tag(2, Tag.GROUP, "group"))
+ ).andReturn(new Request("requestId")).anyTimes();
+ expect(sshKeyPairApi.create(regionId, "prefix"))
+ .andReturn(new KeyPairRequest("requestId", "name", "fingerPrint", "body")).anyTimes();
+
+ replay(securityGroupApi, vSwitchApi, tagApi, sshKeyPairApi, vpcApi, regionAndZoneApi, api, factory, namingConvention, template, location);
+
+ executeAndAssert(vSwitchId, securityGroupId);
+ }
+
+ private void executeAndAssert(String vSwitchId, String securityGroupId) {
+ createResourcesThenCreateNodes.execute("group", 0, template, Collections.<NodeMetadata>emptySet(),
+ Collections.<NodeMetadata, Exception>emptyMap(),
+ ArrayListMultimap.<NodeMetadata, CustomizationResponse>create());
+
+ assertEquals(vSwitchId, templateOptions.getVSwitchId());
+ assertEquals(securityGroupId, templateOptions.getGroups().iterator().next());
+ }
+
+ private SecurityGroup createSecurityGroup(String securityGroupId, String vpcId) {
+ return SecurityGroup.create(
+ securityGroupId,
+ "",
+ "securityGroupName",
+ vpcId,
+ ImmutableMap.<String, List<Tag>>of()
+ );
+ }
+
+ private VSwitch createVSwitch(String vSwitchId, String vpcId) {
+ return VSwitch.create(
+ "",
+ new Date(),
+ "vSwitch",
+ "",
+ VSwitch.Status.AVAILABLE,
+ 1,
+ vpcId,
+ vSwitchId,
+ ""
+ );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/availableZones.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/availableZones.json b/aliyun-ecs/src/test/resources/availableZones.json
new file mode 100644
index 0000000..0b2e092
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/availableZones.json
@@ -0,0 +1,423 @@
+{
+ "RequestId": "C51117E9-1989-4407-AAB6-5E3E433E9A75",
+ "AvailableZones": {
+ "AvailableZone": [
+ {
+ "Status": "Available",
+ "RegionId": "eu-central-1",
+ "AvailableResources": {
+ "AvailableResource": [
+ {
+ "Type": "InstanceType",
+ "SupportedResources": {
+ "SupportedResource": [
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m1.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m4.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m4.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m2.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfg5.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfg5.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m2.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m1.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m4.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfg5.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m1.small"
+ },
+ {
+ "Status": "SoldOut",
+ "Value": "ecs.hfg5.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m2.small"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m1.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc2m1.nano"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m2.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.large"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "ZoneId": "eu-central-1b"
+ },
+ {
+ "Status": "Available",
+ "RegionId": "eu-central-1",
+ "AvailableResources": {
+ "AvailableResource": [
+ {
+ "Type": "InstanceType",
+ "SupportedResources": {
+ "SupportedResource": [
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.n4.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m2.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m4.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfg5.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.mn4.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.i1.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.mn4.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m2.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.e4.small"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m1.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfg5.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m4.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.mn4.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.n4.small"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.i1.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2.large"
+ },
+ {
+ "Status": "SoldOut",
+ "Value": "ecs.ce4.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.ce4.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfg5.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.mn4.small"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m2.small"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m1.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.d1.4xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m2.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.gn5-c4g1.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m1.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2.medium"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-c1m4.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1.medium"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.n4.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfg5.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.gn5-c8g1.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.hfc5.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.i1.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1ne.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.i2.xlarge"
+ },
+ {
+ "Status": "SoldOut",
+ "Value": "ecs.d1.3xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.xn4.small"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc1m1.small"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.d1.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.t5-lc2m1.nano"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.i2.2xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.gn5-c4g1.xlarge"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.se1.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.n4.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn1ne.large"
+ },
+ {
+ "Status": "Available",
+ "Value": "ecs.sn2ne.large"
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "ZoneId": "eu-central-1a"
+ }
+ ]
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/instanceStatus.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/instanceStatus.json b/aliyun-ecs/src/test/resources/instanceStatus.json
new file mode 100644
index 0000000..592ef16
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/instanceStatus.json
@@ -0,0 +1,18 @@
+{
+ "PageNumber": 1,
+ "InstanceStatuses": {
+ "InstanceStatus": [
+ {
+ "Status": "Stopped",
+ "InstanceId": "i-gw8dvsswhc7iifle1hp7"
+ },
+ {
+ "Status": "Stopped",
+ "InstanceId": "i-gw8g25hfbxhyykn3jevq"
+ }
+ ]
+ },
+ "TotalCount": 2,
+ "PageSize": 10,
+ "RequestId": "BDE228AF-8B12-439B-8C1C-FB42CCEB4A65"
+}
\ No newline at end of file
[5/7] jclouds-labs git commit: [JCLOUDS-1430] Aliyun ECS
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitchRequest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitchRequest.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitchRequest.java
new file mode 100644
index 0000000..da16205
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitchRequest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+import java.beans.ConstructorProperties;
+
+public class VSwitchRequest extends Request {
+
+ private final String vSwitchId;
+
+ @ConstructorProperties({ "RequestId", "VSwitchId" })
+ public VSwitchRequest(String requestId, String vSwitchId) {
+ super(requestId);
+ this.vSwitchId = vSwitchId;
+ }
+
+ public String getVSwitchId() {
+ return vSwitchId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+ VSwitchRequest that = (VSwitchRequest) o;
+ return Objects.equal(vSwitchId, that.vSwitchId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), vSwitchId);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("vSwitchId", vSwitchId)
+ .toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VpcAttributes.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VpcAttributes.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VpcAttributes.java
new file mode 100644
index 0000000..f35d6ad
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VpcAttributes.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+import java.util.Map;
+
+@AutoValue
+public abstract class VpcAttributes {
+
+ VpcAttributes() {
+ }
+
+ @SerializedNames({ "NatIpAddress", "PrivateIpAddress", "VSwitchId", "VpcId" })
+ public static VpcAttributes create(String natIpAddress, Map<String, List<String>> privateIpAddress, String vSwitchId,
+ String vpcId) {
+ return new AutoValue_VpcAttributes(natIpAddress,
+ privateIpAddress == null ? ImmutableMap.<String, List<String>>of() : ImmutableMap.copyOf(privateIpAddress),
+ vSwitchId, vpcId);
+ }
+
+ public abstract String natIpAddress();
+
+ public abstract Map<String, List<String>> privateIpAddress();
+
+ public abstract String vSwitchId();
+
+ public abstract String vpcId();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/internal/PaginatedCollection.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/internal/PaginatedCollection.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/internal/PaginatedCollection.java
index 6cffd72..501bed7 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/internal/PaginatedCollection.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/internal/PaginatedCollection.java
@@ -51,8 +51,8 @@ public class PaginatedCollection<T> extends IterableWithMarker<T> {
private final String requestId;
- protected PaginatedCollection(@Nullable Map<String, Iterable<T>> resources, int pageNumber, int totalCount,
- int pageSize, String regionId, String requestId) {
+ public PaginatedCollection(@Nullable Map<String, Iterable<T>> resources, int pageNumber, int totalCount,
+ int pageSize, String regionId, String requestId) {
this.resources = resources != null ? resources : ImmutableMap.<String, Iterable<T>>of();
this.pageNumber = pageNumber;
this.totalCount = totalCount;
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateInstanceOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateInstanceOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateInstanceOptions.java
new file mode 100644
index 0000000..e1c6956
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateInstanceOptions.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+public class CreateInstanceOptions extends BaseHttpRequestOptions {
+ public static final String VSWITCH_PARAM = "VSwitchId";
+ public static final String INSTANCE_NAME_PARAM = "InstanceName";
+ public static final String KEYPAIR_PARAM = "KeyPairName";
+ public static final String INTERNET_CHARGE_TYPE_PARAM = "InternetChargeType";
+ public static final String INTERNET_MAX_BANDWITH_IN_PARAM = "InternetMaxBandwidthIn";
+ public static final String INTERNET_MAX_BANDWITH_OUT_PARAM = "InternetMaxBandwidthOut";
+ public static final String INSTANCE_CHARGE_TYPE_PARAM = "InstanceChargeType";
+
+ /**
+ * Configures the name of the instance to be used.
+ */
+ public CreateInstanceOptions instanceName(String instanceName) {
+ queryParameters.put(INSTANCE_NAME_PARAM, instanceName);
+ return this;
+ }
+
+ /**
+ * Configures the vSwitch Id to be used.
+ */
+ public CreateInstanceOptions vSwitchId(String vSwitchId) {
+ queryParameters.put(VSWITCH_PARAM, vSwitchId);
+ return this;
+ }
+
+ /**
+ * Configures the keyPairName to be used.
+ */
+ public CreateInstanceOptions keyPairName(String keyPairName) {
+ queryParameters.put(KEYPAIR_PARAM, keyPairName);
+ return this;
+ }
+
+ /**
+ * Configures the internet charge type of the instances to be used.
+ */
+ public CreateInstanceOptions internetChargeType(String internetChargeType) {
+ queryParameters.put(INTERNET_CHARGE_TYPE_PARAM, internetChargeType);
+ return this;
+ }
+
+ /**
+ * Configures the internet max bandwidth in of the instances to be used.
+ */
+ public CreateInstanceOptions internetMaxBandwidthIn(int internetMaxBandwidthIn) {
+ queryParameters.put(INTERNET_MAX_BANDWITH_IN_PARAM, String.valueOf(internetMaxBandwidthIn));
+ return this;
+ }
+
+ /**
+ * Configures the internet max bandwidth out of the instances to be used.
+ */
+ public CreateInstanceOptions internetMaxBandwidthOut(int internetMaxBandwidthOut) {
+ queryParameters.put(INTERNET_MAX_BANDWITH_OUT_PARAM, String.valueOf(internetMaxBandwidthOut));
+ return this;
+ }
+
+ /**
+ * Configures the instance charge type of the instances to be used.
+ */
+ public CreateInstanceOptions instanceChargeType(String instanceChargeType) {
+ queryParameters.put(INSTANCE_CHARGE_TYPE_PARAM, instanceChargeType);
+ return this;
+ }
+
+ public CreateInstanceOptions paginationOptions(final PaginationOptions paginationOptions) {
+ this.queryParameters.putAll(paginationOptions.buildQueryParameters());
+ return this;
+ }
+
+ public CreateInstanceOptions tagOptions(final TagOptions tagOptions) {
+ this.queryParameters.putAll(tagOptions.buildQueryParameters());
+ return this;
+ }
+
+ public static final class Builder {
+
+ /**
+ * @see {@link CreateInstanceOptions#instanceName(String)}
+ */
+ public static CreateInstanceOptions instanceName(String instanceName) {
+ return new CreateInstanceOptions().instanceName(instanceName);
+ }
+
+ /**
+ * @see {@link CreateInstanceOptions#vSwitchId(String)}
+ */
+ public static CreateInstanceOptions vSwitchId(String vSwitchId) {
+ return new CreateInstanceOptions().vSwitchId(vSwitchId);
+ }
+
+ /**
+ * @see {@link CreateInstanceOptions#keyPairName(String)}
+ */
+ public static CreateInstanceOptions keyPairName(String keyPairName) {
+ return new CreateInstanceOptions().keyPairName(keyPairName);
+ }
+
+ /**
+ * @see {@link CreateInstanceOptions#internetChargeType(String)}
+ */
+ public static CreateInstanceOptions internetChargeType(String internetChargeType) {
+ return new CreateInstanceOptions().internetChargeType(internetChargeType);
+ }
+
+ /**
+ * @see {@link CreateInstanceOptions#internetMaxBandwidthIn(int)}
+ */
+ public static CreateInstanceOptions internetMaxBandwidthIn(int internetMaxBandwidthIn) {
+ return new CreateInstanceOptions().internetMaxBandwidthIn(internetMaxBandwidthIn);
+ }
+
+ /**
+ * @see {@link CreateInstanceOptions#internetMaxBandwidthOut(int)}
+ */
+ public static CreateInstanceOptions internetMaxBandwidthOut(int internetMaxBandwidthOut) {
+ return new CreateInstanceOptions().internetMaxBandwidthOut(internetMaxBandwidthOut);
+ }
+
+ /**
+ * @see {@link CreateInstanceOptions#instanceChargeType(String)}
+ */
+ public static CreateInstanceOptions instanceChargeType(String instanceChargeType) {
+ return new CreateInstanceOptions().instanceChargeType(instanceChargeType);
+ }
+
+ /**
+ * @see CreateInstanceOptions#paginationOptions(PaginationOptions)
+ */
+ public static CreateInstanceOptions paginationOptions(PaginationOptions paginationOptions) {
+ return new CreateInstanceOptions().paginationOptions(paginationOptions);
+ }
+
+ /**
+ * @see CreateInstanceOptions#tagOptions(TagOptions)
+ */
+ public static CreateInstanceOptions tagOptions(TagOptions tagOptions) {
+ return new CreateInstanceOptions().tagOptions(tagOptions);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVPCOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVPCOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVPCOptions.java
new file mode 100644
index 0000000..b2841b0
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVPCOptions.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+public class CreateVPCOptions extends BaseHttpRequestOptions {
+ public static final String CIDR_BLOCK_PARAM = "CidrBlock";
+ public static final String VPC_NAME_PARAM = "VpcName";
+ public static final String DESCRIPTION_PARAM = "Description";
+ public static final String CLIENT_TOKEN_PARAM = "ClientToken";
+ public static final String USER_CIDR_PARAM = "UserCidr";
+
+ /**
+ * Configures the IP address range of the VPC_PREFIX in the CIDR block form.
+ */
+ public CreateVPCOptions cidrBlock(String cidrBlock) {
+ queryParameters.put(CIDR_BLOCK_PARAM, cidrBlock);
+ return this;
+ }
+
+ /**
+ * Configures the name of the VPC_PREFIX.
+ */
+ public CreateVPCOptions vpcName(String vpcName) {
+ queryParameters.put(VPC_NAME_PARAM, vpcName);
+ return this;
+ }
+
+ /**
+ * Configures the description of the VPC_PREFIX.
+ */
+ public CreateVPCOptions description(String description) {
+ queryParameters.put(DESCRIPTION_PARAM, description);
+ return this;
+ }
+
+ /**
+ * Configures a client token used to guarantee the idempotence of request.
+ */
+ public CreateVPCOptions clientToken(String clientToken) {
+ queryParameters.put(CLIENT_TOKEN_PARAM, clientToken);
+ return this;
+ }
+
+ /**
+ * Configures the user CIDR.
+ */
+ public CreateVPCOptions userCidr(String userCidr) {
+ queryParameters.put(USER_CIDR_PARAM, userCidr);
+ return this;
+ }
+
+ public static final class Builder {
+
+ /**
+ * @see {@link CreateVPCOptions#cidrBlock(String)}
+ */
+ public static CreateVPCOptions cidrBlock(String cidrBlock) {
+ return new CreateVPCOptions().cidrBlock(cidrBlock);
+ }
+
+ /**
+ * @see {@link CreateVPCOptions#vpcName(String)}
+ */
+ public static CreateVPCOptions vpcName(String vpcName) {
+ return new CreateVPCOptions().vpcName(vpcName);
+ }
+
+ /**
+ * @see {@link CreateVPCOptions#description(String)}
+ */
+ public static CreateVPCOptions description(String description) {
+ return new CreateVPCOptions().description(description);
+ }
+
+ /**
+ * @see {@link CreateVPCOptions#clientToken(String)}
+ */
+ public static CreateVPCOptions clientToken(String clientToken) {
+ return new CreateVPCOptions().clientToken(clientToken);
+ }
+
+ /**
+ * @see {@link CreateVPCOptions#userCidr(String)}
+ */
+ public static CreateVPCOptions userCidr(String userCidr) {
+ return new CreateVPCOptions().userCidr(userCidr);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVSwitchOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVSwitchOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVSwitchOptions.java
new file mode 100644
index 0000000..fe10fe5
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/CreateVSwitchOptions.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+public class CreateVSwitchOptions extends BaseHttpRequestOptions {
+ public static final String VSWITCH_NAME_PARAM = "VSwitchName";
+ public static final String DESCRIPTION_PARAM = "Description";
+ public static final String CLIENT_TOKEN_PARAM = "ClientToken";
+
+ /**
+ * Configures the name of the VSwitch.
+ */
+ public CreateVSwitchOptions vSwitchName(String vSwitchName) {
+ queryParameters.put(VSWITCH_NAME_PARAM, vSwitchName);
+ return this;
+ }
+
+ /**
+ * Configures the description of the VPC_PREFIX.
+ */
+ public CreateVSwitchOptions description(String description) {
+ queryParameters.put(DESCRIPTION_PARAM, description);
+ return this;
+ }
+
+ /**
+ * Configures a client token used to guarantee the idempotence of request.
+ */
+ public CreateVSwitchOptions clientToken(String clientToken) {
+ queryParameters.put(CLIENT_TOKEN_PARAM, clientToken);
+ return this;
+ }
+
+ public static final class Builder {
+
+ /**
+ * @see {@link CreateVSwitchOptions#vSwitchName(String)}
+ */
+ public static CreateVSwitchOptions vSwitchName(String vSwitchName) {
+ return new CreateVSwitchOptions().vSwitchName(vSwitchName);
+ }
+
+ /**
+ * @see {@link CreateVSwitchOptions#description(String)}
+ */
+ public static CreateVSwitchOptions description(String description) {
+ return new CreateVSwitchOptions().description(description);
+ }
+
+ /**
+ * @see {@link CreateVSwitchOptions#clientToken(String)}
+ */
+ public static CreateVSwitchOptions clientToken(String clientToken) {
+ return new CreateVSwitchOptions().clientToken(clientToken);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListImagesOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListImagesOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListImagesOptions.java
index 34972a4..0eec663 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListImagesOptions.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListImagesOptions.java
@@ -16,9 +16,11 @@
*/
package org.jclouds.aliyun.ecs.domain.options;
-import org.jclouds.aliyun.ecs.functions.ArrayToCommaSeparatedString;
+import com.google.common.base.Joiner;
import org.jclouds.http.options.BaseHttpRequestOptions;
+import java.util.Arrays;
+
public class ListImagesOptions extends BaseHttpRequestOptions {
public static final String IMAGE_ID_PARAM = "ImageId";
public static final String STATUS_PARAM = "Status";
@@ -28,7 +30,7 @@ public class ListImagesOptions extends BaseHttpRequestOptions {
public static final String USAGE_PARAM = "Usage";
public ListImagesOptions imageIds(String... instanceIds) {
- queryParameters.put(IMAGE_ID_PARAM, String.format("[%s]", new ArrayToCommaSeparatedString().apply(instanceIds)));
+ queryParameters.put(IMAGE_ID_PARAM, Joiner.on(",").join(Arrays.asList(instanceIds)));
return this;
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstanceStatusOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstanceStatusOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstanceStatusOptions.java
new file mode 100644
index 0000000..9d10467
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstanceStatusOptions.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+public class ListInstanceStatusOptions extends BaseHttpRequestOptions {
+ public static final String ZONE_ID_PARAM = "ZoneId";
+
+ public ListInstanceStatusOptions zoneId(String zoneId) {
+ queryParameters.put(ZONE_ID_PARAM, zoneId);
+ return this;
+ }
+
+ public ListInstanceStatusOptions paginationOptions(final PaginationOptions paginationOptions) {
+ this.queryParameters.putAll(paginationOptions.buildQueryParameters());
+ return this;
+ }
+
+ public static final class Builder {
+
+ /**
+ * @see {@link ListInstanceStatusOptions#zoneId(String)}
+ */
+ public static ListInstanceStatusOptions zoneId(String zoneId) {
+ return new ListInstanceStatusOptions().zoneId(zoneId);
+ }
+
+ /**
+ * @see ListInstanceStatusOptions#paginationOptions(PaginationOptions)
+ */
+ public static ListInstanceStatusOptions paginationOptions(PaginationOptions paginationOptions) {
+ return new ListInstanceStatusOptions().paginationOptions(paginationOptions);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstancesOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstancesOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstancesOptions.java
new file mode 100644
index 0000000..ec39383
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListInstancesOptions.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.options;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.Iterables;
+import org.jclouds.aliyun.ecs.functions.PutStringInDoubleQuotes;
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+import java.util.Arrays;
+
+public class ListInstancesOptions extends BaseHttpRequestOptions {
+ public static final String VPC_ID_PARAM = "VpcId";
+ public static final String VSWITCH_ID_PARAM = "VSwitchId";
+ public static final String ZONE_ID_PARAM = "ZoneId";
+ public static final String INSTANCE_IDS_PARAM = "InstanceIds";
+ public static final String INSTANCE_TYPE_PARAM = "InstanceType";
+ public static final String INSTANCE_TYPE_FAMILY_PARAM = "InstanceTypeFamily";
+ public static final String INSTANCE_NETWORK_TYPE_PARAM = "InstanceNetworkType";
+ public static final String PRIVATE_IP_ADDRESSES_PARAM = "PrivateIpAddresses";
+ public static final String INNER_IP_ADDRESSES_PARAM = "InnerIpAddresses";
+ public static final String PUBLIC_IP_ADDRESSES_PARAM = "PublicIpAddresses";
+ public static final String SECURITY_GROUP_ID_PARAM = "SecurityGroupId";
+ public static final String INSTANCE_CHARGE_TYPE_PARAM = "InstanceChargeType";
+ public static final String SPOT_STRATEGY_PARAM = "SpotStrategy";
+ public static final String INTERNET_CHARGE_TYPE_PARAM = "InternetChargeType";
+ public static final String INSTANCE_NAME_PARAM = "InstanceName";
+ public static final String IMAGE_ID_PARAM = "ImageId";
+ public static final String DEPLOYMENT_SET_ID_PARAM = "DeploymentSetId";
+ public static final String STATUS_PARAM = "Status";
+ public static final String IO_OPTIMIZED_PARAM = "IoOptimized";
+
+ public ListInstancesOptions vpcId(String vpcId) {
+ queryParameters.put(VPC_ID_PARAM, vpcId);
+ return this;
+ }
+
+ public ListInstancesOptions vSwitchId(String vSwitchId) {
+ queryParameters.put(VSWITCH_ID_PARAM, vSwitchId);
+ return this;
+ }
+
+ public ListInstancesOptions zoneId(String zoneId) {
+ queryParameters.put(ZONE_ID_PARAM, zoneId);
+ return this;
+ }
+
+ public ListInstancesOptions instanceIds(String... instanceIds) {
+ String instanceIdsAsString = Joiner.on(",")
+ .join(Iterables.transform(Arrays.asList(instanceIds), new PutStringInDoubleQuotes()));
+ queryParameters.put(INSTANCE_IDS_PARAM, String.format("[%s]", instanceIdsAsString));
+ return this;
+ }
+
+ public ListInstancesOptions instanceType(String instanceType) {
+ queryParameters.put(INSTANCE_TYPE_PARAM, instanceType);
+ return this;
+ }
+
+ public ListInstancesOptions instanceTypeFamily(String instanceTypeFamily) {
+ queryParameters.put(INSTANCE_TYPE_FAMILY_PARAM, instanceTypeFamily);
+ return this;
+ }
+
+ public ListInstancesOptions instanceNetworkType(String instanceNetworkType) {
+ queryParameters.put(INSTANCE_NETWORK_TYPE_PARAM, instanceNetworkType);
+ return this;
+ }
+
+ public ListInstancesOptions privateIpAddresses(String... privateIpAddresses) {
+ String instanceIdsAsString = Joiner.on(",")
+ .join(Iterables.transform(Arrays.asList(privateIpAddresses), new PutStringInDoubleQuotes()));
+ queryParameters.put(PRIVATE_IP_ADDRESSES_PARAM, String.format("[%s]", instanceIdsAsString));
+ return this;
+ }
+
+ public ListInstancesOptions innerIpAddresses(String... innerIpAddresses) {
+ String instanceIdsAsString = Joiner.on(",")
+ .join(Iterables.transform(Arrays.asList(innerIpAddresses), new PutStringInDoubleQuotes()));
+ queryParameters.put(INNER_IP_ADDRESSES_PARAM, String.format("[%s]", instanceIdsAsString));
+ return this;
+ }
+
+ public ListInstancesOptions publicIpAddresses(String... publicIpAddresses) {
+ String instanceIdsAsString = Joiner.on(",")
+ .join(Iterables.transform(Arrays.asList(publicIpAddresses), new PutStringInDoubleQuotes()));
+ queryParameters.put(PUBLIC_IP_ADDRESSES_PARAM, String.format("[%s]", instanceIdsAsString));
+ return this;
+ }
+
+ public ListInstancesOptions securityGroupId(String securityGroupId) {
+ queryParameters.put(SECURITY_GROUP_ID_PARAM, securityGroupId);
+ return this;
+ }
+
+ public ListInstancesOptions instanceChargeType(String instanceChargeType) {
+ queryParameters.put(INSTANCE_CHARGE_TYPE_PARAM, instanceChargeType);
+ return this;
+ }
+
+ public ListInstancesOptions spotStrategy(String spotStrategy) {
+ queryParameters.put(SPOT_STRATEGY_PARAM, spotStrategy);
+ return this;
+ }
+
+ public ListInstancesOptions internetChargeType(String internetChargeType) {
+ queryParameters.put(INTERNET_CHARGE_TYPE_PARAM, internetChargeType);
+ return this;
+ }
+
+ public ListInstancesOptions instanceName(String instanceName) {
+ queryParameters.put(INSTANCE_NAME_PARAM, instanceName);
+ return this;
+ }
+
+ public ListInstancesOptions imageId(String imageId) {
+ queryParameters.put(IMAGE_ID_PARAM, imageId);
+ return this;
+ }
+
+ public ListInstancesOptions deploymentSetId(String deploymentSetId) {
+ queryParameters.put(DEPLOYMENT_SET_ID_PARAM, deploymentSetId);
+ return this;
+ }
+
+ public ListInstancesOptions status(String status) {
+ queryParameters.put(STATUS_PARAM, status);
+ return this;
+ }
+
+ public ListInstancesOptions ioOptimized(String ioOptimized) {
+ queryParameters.put(IO_OPTIMIZED_PARAM, ioOptimized);
+ return this;
+ }
+
+ public ListInstancesOptions paginationOptions(final PaginationOptions paginationOptions) {
+ this.queryParameters.putAll(paginationOptions.buildQueryParameters());
+ return this;
+ }
+
+ public ListInstancesOptions tagOptions(final TagOptions tagOptions) {
+ this.queryParameters.putAll(tagOptions.buildQueryParameters());
+ return this;
+ }
+
+ public static final class Builder {
+
+ public static ListInstancesOptions vpcId(String vpcId) {
+ return new ListInstancesOptions().vpcId(vpcId);
+ }
+
+ public static ListInstancesOptions vSwitchId(String vSwitchId) {
+ return new ListInstancesOptions().vSwitchId(vSwitchId);
+ }
+
+ public static ListInstancesOptions zoneId(String zoneId) {
+ return new ListInstancesOptions().zoneId(zoneId);
+ }
+
+ public static ListInstancesOptions instanceIds(String... instanceIds) {
+ return new ListInstancesOptions().instanceIds(instanceIds);
+ }
+
+ public static ListInstancesOptions instanceType(String instanceType) {
+ return new ListInstancesOptions().instanceType(instanceType);
+ }
+
+ public static ListInstancesOptions instanceTypeFamily(String instanceTypeFamily) {
+ return new ListInstancesOptions().instanceTypeFamily(instanceTypeFamily);
+ }
+
+ public static ListInstancesOptions instanceNetworkType(String instanceNetworkType) {
+ return new ListInstancesOptions().instanceNetworkType(instanceNetworkType);
+ }
+
+ public static ListInstancesOptions privateIpAddresses(String... privateIpAddresses) {
+ return new ListInstancesOptions().privateIpAddresses(privateIpAddresses);
+ }
+
+ public static ListInstancesOptions innerIpAddresses(String... innerIpAddresses) {
+ return new ListInstancesOptions().innerIpAddresses(innerIpAddresses);
+ }
+
+ public static ListInstancesOptions publicIpAddresses(String... publicIpAddresses) {
+ return new ListInstancesOptions().publicIpAddresses(publicIpAddresses);
+ }
+
+ public static ListInstancesOptions securityGroupId(String securityGroupId) {
+ return new ListInstancesOptions().securityGroupId(securityGroupId);
+ }
+
+ public static ListInstancesOptions instanceChargeType(String instanceChargeType) {
+ return new ListInstancesOptions().instanceChargeType(instanceChargeType);
+ }
+
+ public static ListInstancesOptions instanceName(String instanceName) {
+ return new ListInstancesOptions().instanceName(instanceName);
+ }
+
+ public static ListInstancesOptions imageId(String imageId) {
+ return new ListInstancesOptions().imageId(imageId);
+ }
+
+ public static ListInstancesOptions deploymentSetId(String deploymentSetId) {
+ return new ListInstancesOptions().deploymentSetId(deploymentSetId);
+ }
+
+ public static ListInstancesOptions status(String status) {
+ return new ListInstancesOptions().status(status);
+ }
+
+ public static ListInstancesOptions ioOptimized(String ioOptimized) {
+ return new ListInstancesOptions().ioOptimized(ioOptimized);
+ }
+
+ public static ListInstancesOptions paginationOptions(PaginationOptions paginationOptions) {
+ return new ListInstancesOptions().paginationOptions(paginationOptions);
+ }
+
+ public static ListInstancesOptions tagOptions(TagOptions tagOptions) {
+ return new ListInstancesOptions().tagOptions(tagOptions);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVPCsOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVPCsOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVPCsOptions.java
new file mode 100644
index 0000000..8915251
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVPCsOptions.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+public class ListVPCsOptions extends BaseHttpRequestOptions {
+ public static final String VPC_ID_PARAM = "VpcId";
+ public static final String IS_DEFAULT_PARAM = "IsDefault";
+
+ public ListVPCsOptions vpcId(String vpcId) {
+ queryParameters.put(VPC_ID_PARAM, vpcId);
+ return this;
+ }
+
+ public ListVPCsOptions isDefault(Boolean isDefault) {
+ queryParameters.put(IS_DEFAULT_PARAM, isDefault.toString());
+ return this;
+ }
+
+ public ListVPCsOptions paginationOptions(final PaginationOptions paginationOptions) {
+ this.queryParameters.putAll(paginationOptions.buildQueryParameters());
+ return this;
+ }
+
+ public static final class Builder {
+
+ /**
+ * @see {@link ListVSwitchesOptions#vpcId(String)}
+ */
+ public static ListVPCsOptions vpcId(String vpcId) {
+ return new ListVPCsOptions().vpcId(vpcId);
+ }
+
+ /**
+ * @see {@link ListVPCsOptions#isDefault(Boolean)}
+ */
+ public static ListVPCsOptions isDefault(Boolean isDefault) {
+ return new ListVPCsOptions().isDefault(isDefault);
+ }
+
+ /**
+ * @see ListVPCsOptions#paginationOptions(PaginationOptions)
+ */
+ public static ListVPCsOptions paginationOptions(PaginationOptions paginationOptions) {
+ return new ListVPCsOptions().paginationOptions(paginationOptions);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVSwitchesOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVSwitchesOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVSwitchesOptions.java
new file mode 100644
index 0000000..8661175
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/ListVSwitchesOptions.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.options;
+
+import org.jclouds.http.options.BaseHttpRequestOptions;
+
+public class ListVSwitchesOptions extends BaseHttpRequestOptions {
+ public static final String VPC_ID_PARAM = "VpcId";
+ public static final String VSWITCH_ID_PARAM = "VSwitchId";
+ public static final String ZONE_ID_PARAM = "ZoneId";
+ public static final String IS_DEFAULT_PARAM = "IsDefault";
+
+ public ListVSwitchesOptions vpcId(String vpcId) {
+ queryParameters.put(VPC_ID_PARAM, vpcId);
+ return this;
+ }
+
+ public ListVSwitchesOptions vSwitchId(String vSwitchId) {
+ queryParameters.put(VSWITCH_ID_PARAM, vSwitchId);
+ return this;
+ }
+
+ public ListVSwitchesOptions zoneId(String zoneId) {
+ queryParameters.put(ZONE_ID_PARAM, zoneId);
+ return this;
+ }
+
+ public ListVSwitchesOptions isDefault(Boolean isDefault) {
+ queryParameters.put(IS_DEFAULT_PARAM, isDefault.toString());
+ return this;
+ }
+
+ public ListVSwitchesOptions paginationOptions(final PaginationOptions paginationOptions) {
+ this.queryParameters.putAll(paginationOptions.buildQueryParameters());
+ return this;
+ }
+
+ public static final class Builder {
+
+ /**
+ * @see {@link ListVSwitchesOptions#vpcId(String)}
+ */
+ public static ListVSwitchesOptions vpcId(String vpcId) {
+ return new ListVSwitchesOptions().vpcId(vpcId);
+ }
+
+ /**
+ * @see {@link ListVSwitchesOptions#vSwitchId(String)}
+ */
+ public static ListVSwitchesOptions vSwitchId(String vSwitchId) {
+ return new ListVSwitchesOptions().vSwitchId(vSwitchId);
+ }
+
+ /**
+ * @see {@link ListVSwitchesOptions#zoneId(String)}
+ */
+ public static ListVSwitchesOptions zoneId(String zoneId) {
+ return new ListVSwitchesOptions().zoneId(zoneId);
+ }
+
+ /**
+ * @see {@link ListVSwitchesOptions#isDefault(Boolean)}
+ */
+ public static ListVSwitchesOptions isDefault(Boolean isDefault) {
+ return new ListVSwitchesOptions().isDefault(isDefault);
+ }
+
+ /**
+ * @see ListVSwitchesOptions#paginationOptions(PaginationOptions)
+ */
+ public static ListVSwitchesOptions paginationOptions(PaginationOptions paginationOptions) {
+ return new ListVSwitchesOptions().paginationOptions(paginationOptions);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/TagOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/TagOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/TagOptions.java
index 4e3068e..f220fcd 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/TagOptions.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/options/TagOptions.java
@@ -21,8 +21,8 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import org.jclouds.http.options.BaseHttpRequestOptions;
-import javax.annotation.Nullable;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -66,6 +66,16 @@ public class TagOptions extends BaseHttpRequestOptions {
return this;
}
+ public TagOptions tags(Map<String, String> tags) {
+ checkState(tags.size() <= 5, "tags size must be <= 5");
+ int i = 1;
+ for (Map.Entry<String, String> entry : tags.entrySet()) {
+ tag(i, entry.getKey(), entry.getValue());
+ i++;
+ }
+ return this;
+ }
+
public static class Builder {
public static TagOptions tag(int pos, String key, String value) {
@@ -79,6 +89,10 @@ public class TagOptions extends BaseHttpRequestOptions {
public static TagOptions keys(Set<String> keys) {
return new TagOptions().keys(keys);
}
+
+ public static TagOptions tags(Map<String, String> tags) {
+ return new TagOptions().tags(tags);
+ }
}
private void validateInput(final String input, int maxLength) {
@@ -86,10 +100,10 @@ public class TagOptions extends BaseHttpRequestOptions {
checkState(input.length() <= maxLength, String.format("input must be <= %d chars", maxLength));
checkState(!Iterables.any(FORBIDDEN_PREFIX, new Predicate<String>() {
@Override
- public boolean apply(@Nullable String input) {
- return input.startsWith(input);
+ public boolean apply(String forbiddenPrefix) {
+ return input.startsWith(forbiddenPrefix);
}
- }), "Cannot starts with " + Iterables.toString(FORBIDDEN_PREFIX));
+ }), input + " cannot starts with any of " + Iterables.toString(FORBIDDEN_PREFIX));
}
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/ImageInRegion.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/ImageInRegion.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/ImageInRegion.java
new file mode 100644
index 0000000..5a5bf4f
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/ImageInRegion.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.regionscoped;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.aliyun.ecs.domain.Image;
+
+
+@AutoValue
+public abstract class ImageInRegion {
+
+ ImageInRegion() {}
+
+ public abstract String regionId();
+ public abstract Image image();
+
+ public static ImageInRegion create(String regionId, Image image) {
+ return new AutoValue_ImageInRegion(regionId, image);
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/RegionAndId.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/RegionAndId.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/RegionAndId.java
new file mode 100644
index 0000000..6d2a392
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/regionscoped/RegionAndId.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain.regionscoped;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+@AutoValue
+public abstract class RegionAndId {
+
+ RegionAndId() {}
+
+ public static RegionAndId create(String regionId, String id) {
+ return new AutoValue_RegionAndId(regionId, id);
+ }
+
+ public static RegionAndId fromSlashEncoded(String id) {
+ Iterable<String> parts = Splitter.on('/').split(checkNotNull(id, "id"));
+ checkArgument(Iterables.size(parts) == 2, "id must be in format regionId/id");
+ return RegionAndId.create(Iterables.get(parts, 0), Iterables.get(parts, 1));
+ }
+
+ public static String slashEncodeRegionAndId(String regionId, String id) {
+ return slashEncodeRegionAndId(RegionAndId.create(regionId, id));
+ }
+
+ public static String slashEncodeRegionAndId(RegionAndId regionAndId) {
+ checkNotNull(regionAndId, "regionAndId");
+ return String.format("%s/%s", regionAndId.regionId(), regionAndId.id());
+ }
+
+ public abstract String regionId();
+
+ public abstract String id();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/InstanceApi.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/InstanceApi.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/InstanceApi.java
new file mode 100644
index 0000000..457a3ac
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/InstanceApi.java
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.features;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.inject.TypeLiteral;
+import org.jclouds.Constants;
+import org.jclouds.Fallbacks;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.domain.AllocatePublicIpAddressRequest;
+import org.jclouds.aliyun.ecs.domain.AvailableZone;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.InstanceRequest;
+import org.jclouds.aliyun.ecs.domain.InstanceStatus;
+import org.jclouds.aliyun.ecs.domain.InstanceType;
+import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.internal.PaginatedCollection;
+import org.jclouds.aliyun.ecs.domain.options.CreateInstanceOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListInstanceStatusOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListInstancesOptions;
+import org.jclouds.aliyun.ecs.domain.options.PaginationOptions;
+import org.jclouds.aliyun.ecs.filters.FormSign;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.collect.internal.ArgsToPagedIterable;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.Transform;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.beans.ConstructorProperties;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * https://www.alibabacloud.com/help/doc-detail/25500.htm?spm=a2c63.p38356.b99.287.129a44a8RBMBLH
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(FormSign.class)
+@QueryParams(keys = { "Version", "Format", "SignatureVersion", "ServiceCode", "SignatureMethod" },
+ values = {"{" + Constants.PROPERTY_API_VERSION + "}", "JSON", "1.0", "ecs", "HMAC-SHA1"})
+public interface InstanceApi {
+
+ @Named("instance:list")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeInstances")
+ @ResponseParser(ParseInstances.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ IterableWithMarker<Instance> list(@QueryParam("RegionId") String region, ListInstancesOptions options);
+
+ @Named("instance:list")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeInstances")
+ @ResponseParser(ParseInstances.class)
+ @Transform(ParseInstances.ToPagedIterable.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<Instance> list(@QueryParam("RegionId") String region);
+
+ @Named("instanceType:list")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeInstanceTypes")
+ @SelectJson("InstanceType")
+ @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+ List<InstanceType> listTypes();
+
+ @Named("instanceType:list")
+ @GET
+ @QueryParams(keys = { "Action", "DestinationResource", "IoOptimized" },
+ values = { "DescribeAvailableResource", "InstanceType", "optimized" })
+ @SelectJson("AvailableZone")
+ @Fallback(Fallbacks.EmptyListOnNotFoundOr404.class)
+ List<AvailableZone> listInstanceTypesByAvailableZone(@QueryParam("RegionId") String regionId);
+
+ @Named("instance:create")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = "Action", values = "CreateInstance")
+ InstanceRequest create(@QueryParam("RegionId") String regionId,
+ @QueryParam("ImageId") String imageId,
+ @QueryParam("SecurityGroupId") String securityGroupId,
+ @QueryParam("HostName") String hostname,
+ @QueryParam("InstanceType") String instanceType);
+
+ @Named("instance:create")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = "Action", values = "CreateInstance")
+ InstanceRequest create(@QueryParam("RegionId") String regionId,
+ @QueryParam("ImageId") String imageId,
+ @QueryParam("SecurityGroupId") String securityGroupId,
+ @QueryParam("HostName") String hostname,
+ @QueryParam("InstanceType") String instanceType,
+ CreateInstanceOptions options);
+
+ @Named("instance:allocatePublicIpAddress")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = "Action", values = "AllocatePublicIpAddress")
+ AllocatePublicIpAddressRequest allocatePublicIpAddress(@QueryParam("RegionId") String regionId,
+ @QueryParam("InstanceId") String instanceId);
+
+ @Named("instance:listInstanceStatus")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeInstanceStatus")
+ @ResponseParser(ParseInstanceStatus.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ IterableWithMarker<InstanceStatus> listInstanceStatus(@QueryParam("RegionId") String region, ListInstanceStatusOptions options);
+
+ @Named("instance:listInstanceStatus")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeInstanceStatus")
+ @ResponseParser(ParseInstanceStatus.class)
+ @Transform(ParseInstanceStatus.ToPagedIterable.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<InstanceStatus> listInstanceStatus(@QueryParam("RegionId") String region);
+
+ /**
+ * You can only release an instance that is in the Stopped (Stopped) status.
+ *
+ * @param instanceId
+ */
+ @Named("instance:delete")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = "Action", values = "DeleteInstance")
+ @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+ Request delete(@QueryParam("InstanceId") String instanceId);
+
+ @Named("instance:powerOff")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = "Action", values = "StopInstance")
+ Request powerOff(@QueryParam("InstanceId") String instanceId);
+
+ @Named("instance:powerOn")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = "Action", values = "StartInstance")
+ Request powerOn(@QueryParam("InstanceId") String instanceId);
+
+ @Named("instance:reboot")
+ @POST
+ @Produces(MediaType.APPLICATION_JSON)
+ @QueryParams(keys = "Action", values = "RebootInstance")
+ Request reboot(@QueryParam("InstanceId") String instanceId);
+
+ @Singleton
+ final class ParseInstances extends ParseJson<ParseInstances.Instances> {
+
+ @Inject
+ ParseInstances(final Json json) {
+ super(json, TypeLiteral.get(Instances.class));
+ }
+
+ private static class Instances extends PaginatedCollection<Instance> {
+
+ @ConstructorProperties({ "Instances", "PageNumber", "TotalCount", "PageSize", "RegionId", "RequestId" })
+ public Instances(Map<String, Iterable<Instance>> content, Integer pageNumber, Integer totalCount, Integer pageSize, String regionId, String requestId) {
+ super(content, pageNumber, totalCount, pageSize, regionId, requestId);
+ }
+ }
+
+ private static class ToPagedIterable extends ArgsToPagedIterable<Instance, ToPagedIterable> {
+
+ private ECSComputeServiceApi api;
+
+ @Inject
+ ToPagedIterable(final ECSComputeServiceApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<Instance>> markerToNextForArgs(List<Object> args) {
+ if (args == null || args.isEmpty()) throw new IllegalStateException("Can't advance the PagedIterable");
+ final String regionId = args.get(0).toString();
+ final ListInstancesOptions original = (ListInstancesOptions) Iterables.tryFind(args, Predicates.instanceOf(ListInstancesOptions.class)).orNull();
+
+ return new Function<Object, IterableWithMarker<Instance>>() {
+ @Override
+ public IterableWithMarker<Instance> apply(Object input) {
+ ListInstancesOptions options = original == null ?
+ ListInstancesOptions.Builder.paginationOptions(PaginationOptions.class.cast(input)) :
+ original.paginationOptions(PaginationOptions.class.cast(input));
+ return api.instanceApi().list(regionId, options);
+ }
+ };
+ }
+ }
+ }
+
+ @Singleton
+ final class ParseInstanceStatus extends ParseJson<ParseInstanceStatus.InstanceStatuses> {
+
+ @Inject
+ ParseInstanceStatus(final Json json) {
+ super(json, TypeLiteral.get(InstanceStatuses.class));
+ }
+
+ private static class InstanceStatuses extends PaginatedCollection<InstanceStatus> {
+
+ @ConstructorProperties({ "InstanceStatuses", "PageNumber", "TotalCount", "PageSize", "RegionId", "RequestId" })
+ public InstanceStatuses(Map<String, Iterable<InstanceStatus>> content, Integer pageNumber, Integer totalCount, Integer pageSize, String regionId, String requestId) {
+ super(content, pageNumber, totalCount, pageSize, regionId, requestId);
+ }
+ }
+
+ private static class ToPagedIterable extends ArgsToPagedIterable<InstanceStatus, ToPagedIterable> {
+
+ private ECSComputeServiceApi api;
+
+ @Inject
+ ToPagedIterable(final ECSComputeServiceApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<InstanceStatus>> markerToNextForArgs(List<Object> args) {
+ if (args == null || args.isEmpty()) throw new IllegalStateException("Can't advance the PagedIterable");
+ final String regionId = args.get(0).toString();
+ final ListInstanceStatusOptions original = (ListInstanceStatusOptions) Iterables.tryFind(args, Predicates.instanceOf(ListInstanceStatusOptions.class)).orNull();
+
+ return new Function<Object, IterableWithMarker<InstanceStatus>>() {
+ @Override
+ public IterableWithMarker<InstanceStatus> apply(Object input) {
+ ListInstanceStatusOptions options = original == null ?
+ ListInstanceStatusOptions.Builder.paginationOptions(PaginationOptions.class.cast(input)) :
+ original.paginationOptions(PaginationOptions.class.cast(input));
+ return api.instanceApi().listInstanceStatus(regionId, options);
+ }
+ };
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SecurityGroupApi.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SecurityGroupApi.java
index c70bcb6..9b36bf8 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SecurityGroupApi.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SecurityGroupApi.java
@@ -57,6 +57,9 @@ import java.beans.ConstructorProperties;
import java.util.List;
import java.util.Map;
+/**
+ * https://www.alibabacloud.com/help/doc-detail/25553.htm?spm=a2c63.p38356.b99.323.1a3b59abPkInRB
+ */
@Consumes(MediaType.APPLICATION_JSON)
@RequestFilters(FormSign.class)
@QueryParams(keys = {"Version", "Format", "SignatureVersion", "ServiceCode", "SignatureMethod"},
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SshKeyPairApi.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SshKeyPairApi.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SshKeyPairApi.java
index b207335..41e9937 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SshKeyPairApi.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/SshKeyPairApi.java
@@ -55,6 +55,9 @@ import java.beans.ConstructorProperties;
import java.util.List;
import java.util.Map;
+/**
+ * https://www.alibabacloud.com/help/doc-detail/51771.htm?spm=a2c63.p38356.b99.338.1da53569DqQAVv
+ */
@Consumes(MediaType.APPLICATION_JSON)
@RequestFilters(FormSign.class)
@QueryParams(keys = { "Version", "Format", "SignatureVersion", "ServiceCode", "SignatureMethod" },
@@ -135,6 +138,7 @@ public interface SshKeyPairApi {
@Named("sshKeyPair:delete")
@POST
@QueryParams(keys = "Action", values = "DeleteKeyPairs")
+ @Fallback(Fallbacks.NullOnNotFoundOr404.class)
Request delete(@QueryParam("RegionId") String region,
@ParamParser(ArrayToCommaSeparatedString.class) @QueryParam("KeyPairNames") String... keyPairNames);
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/TagApi.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/TagApi.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/TagApi.java
index 67c3b82..e75c086 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/TagApi.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/TagApi.java
@@ -24,6 +24,7 @@ import org.jclouds.Constants;
import org.jclouds.Fallbacks;
import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.ResourceType;
import org.jclouds.aliyun.ecs.domain.Tag;
import org.jclouds.aliyun.ecs.domain.internal.PaginatedCollection;
import org.jclouds.aliyun.ecs.domain.options.ListTagsOptions;
@@ -53,6 +54,9 @@ import java.beans.ConstructorProperties;
import java.util.List;
import java.util.Map;
+/**
+ * https://www.alibabacloud.com/help/doc-detail/25616.htm?spm=a2c63.p38356.b99.382.580b30373FFIDb
+ */
@Consumes(MediaType.APPLICATION_JSON)
@RequestFilters(FormSign.class)
@QueryParams(keys = { "Version", "Format", "SignatureVersion", "ServiceCode", "SignatureMethod" },
@@ -122,7 +126,7 @@ public interface TagApi {
@POST
@QueryParams(keys = "Action", values = "AddTags")
Request add(@QueryParam("RegionId") String region, @QueryParam("ResourceId") String resourceId,
- @QueryParam("ResourceType") String resourceType,
+ @QueryParam("ResourceType") ResourceType resourceType,
TagOptions tagOptions);
@Named("tag:remove")
@@ -130,14 +134,14 @@ public interface TagApi {
@QueryParams(keys = "Action", values = "RemoveTags")
Request remove(@QueryParam("RegionId") String region,
@QueryParam("ResourceId") String resourceId,
- @QueryParam("ResourceType") String resourceType);
+ @QueryParam("ResourceType") ResourceType resourceType);
@Named("tag:remove")
@POST
@QueryParams(keys = "Action", values = "RemoveTags")
Request remove(@QueryParam("RegionId") String region,
@QueryParam("ResourceId") String resourceId,
- @QueryParam("ResourceType") String resourceType,
+ @QueryParam("ResourceType") ResourceType resourceType,
TagOptions options);
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VPCApi.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VPCApi.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VPCApi.java
new file mode 100644
index 0000000..f2e9e5f
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VPCApi.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.features;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.inject.TypeLiteral;
+import org.jclouds.Constants;
+import org.jclouds.Fallbacks;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.VPC;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.aliyun.ecs.domain.internal.PaginatedCollection;
+import org.jclouds.aliyun.ecs.domain.options.CreateVPCOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVPCsOptions;
+import org.jclouds.aliyun.ecs.domain.options.PaginationOptions;
+import org.jclouds.aliyun.ecs.filters.FormSign;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.collect.internal.ArgsToPagedIterable;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.Transform;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.beans.ConstructorProperties;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * https://www.alibabacloud.com/help/doc-detail/35737.htm?spm=a2c63.p38356.b99.44.2554c880ZhTTkh
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(FormSign.class)
+@QueryParams(keys = { "Version", "Format", "SignatureVersion", "ServiceCode", "SignatureMethod" },
+ values = {"{" + Constants.PROPERTY_API_VERSION + "}", "JSON", "1.0", "ecs", "HMAC-SHA1"})
+public interface VPCApi {
+
+ @Named("vpc:list")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeVpcs")
+ @ResponseParser(ParseVPCs.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ IterableWithMarker<VPC> list(@QueryParam("RegionId") String region, ListVPCsOptions options);
+
+ @Named("vpc:list")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeVpcs")
+ @ResponseParser(ParseVPCs.class)
+ @Transform(ParseVPCs.ToPagedIterable.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<VPC> list(@QueryParam("RegionId") String region);
+
+ @Singleton
+ final class ParseVPCs extends ParseJson<ParseVPCs.VPCs> {
+
+ private static class VPCs extends PaginatedCollection<VPC> {
+
+ @ConstructorProperties({ "Vpcs", "PageNumber", "TotalCount", "PageSize", "RegionId", "RequestId" })
+ public VPCs(Map<String, Iterable<VPC>> content, Integer pageNumber, Integer totalCount, Integer pageSize, String regionId, String requestId) {
+ super(content, pageNumber, totalCount, pageSize, regionId, requestId);
+ }
+ }
+ @Inject
+ ParseVPCs(final Json json) {
+ super(json, TypeLiteral.get(VPCs.class));
+ }
+
+ static class ToPagedIterable extends ArgsToPagedIterable<VPC, ToPagedIterable> {
+
+ private final ECSComputeServiceApi api;
+
+ @Inject
+ ToPagedIterable(ECSComputeServiceApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<VPC>> markerToNextForArgs(List<Object> args) {
+ if (args == null || args.isEmpty()) throw new IllegalStateException("Can't advance the PagedIterable");
+ final String regionId = args.get(0).toString();
+ final ListVPCsOptions original = (ListVPCsOptions) Iterables.tryFind(args, Predicates.instanceOf(ListVPCsOptions.class)).orNull();
+
+ return new Function<Object, IterableWithMarker<VPC>>() {
+ @Override
+ public IterableWithMarker<VPC> apply(Object input) {
+ ListVPCsOptions options = original == null ?
+ ListVPCsOptions.Builder.paginationOptions(PaginationOptions.class.cast(input)) :
+ original.paginationOptions(PaginationOptions.class.cast(input));
+ return api.vpcApi().list(regionId, options);
+ }
+ };
+ }
+ }
+ }
+
+ @Named("vpc:create")
+ @POST
+ @QueryParams(keys = "Action", values = "CreateVpc")
+ VPCRequest create(@QueryParam("RegionId") String region);
+
+ @Named("vpc:create")
+ @POST
+ @QueryParams(keys = "Action", values = "CreateVpc")
+ VPCRequest create(@QueryParam("RegionId") String region, CreateVPCOptions vpcOptions);
+
+ @Named("vpc:delete")
+ @POST
+ @QueryParams(keys = "Action", values = "DeleteVpc")
+ Request delete(@QueryParam("RegionId") String region,
+ @QueryParam("VpcId") String vpcId);
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VSwitchApi.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VSwitchApi.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VSwitchApi.java
new file mode 100644
index 0000000..5508ea1
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/features/VSwitchApi.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.features;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.inject.TypeLiteral;
+import org.jclouds.Constants;
+import org.jclouds.Fallbacks;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.domain.Request;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.VSwitchRequest;
+import org.jclouds.aliyun.ecs.domain.internal.PaginatedCollection;
+import org.jclouds.aliyun.ecs.domain.options.CreateVSwitchOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions;
+import org.jclouds.aliyun.ecs.domain.options.PaginationOptions;
+import org.jclouds.aliyun.ecs.filters.FormSign;
+import org.jclouds.collect.IterableWithMarker;
+import org.jclouds.collect.PagedIterable;
+import org.jclouds.collect.internal.ArgsToPagedIterable;
+import org.jclouds.http.functions.ParseJson;
+import org.jclouds.json.Json;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.QueryParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.ResponseParser;
+import org.jclouds.rest.annotations.Transform;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import java.beans.ConstructorProperties;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * https://www.alibabacloud.com/help/doc-detail/35745.htm
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(FormSign.class)
+@QueryParams(keys = { "Version", "Format", "SignatureVersion", "ServiceCode", "SignatureMethod" },
+ values = {"{" + Constants.PROPERTY_API_VERSION + "}", "JSON", "1.0", "ecs", "HMAC-SHA1"})
+public interface VSwitchApi {
+
+ @Named("vswitch:list")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeVSwitches")
+ @ResponseParser(ParseVSwitches.class)
+ @Fallback(Fallbacks.EmptyIterableWithMarkerOnNotFoundOr404.class)
+ IterableWithMarker<VSwitch> list(@QueryParam("RegionId") String region, ListVSwitchesOptions options);
+
+ @Named("vswitch:list")
+ @GET
+ @QueryParams(keys = "Action", values = "DescribeVSwitches")
+ @ResponseParser(ParseVSwitches.class)
+ @Transform(ParseVSwitches.ToPagedIterable.class)
+ @Fallback(Fallbacks.EmptyPagedIterableOnNotFoundOr404.class)
+ PagedIterable<VSwitch> list(@QueryParam("RegionId") String region);
+
+ @Singleton
+ final class ParseVSwitches extends ParseJson<ParseVSwitches.VSwitches> {
+
+ private static class VSwitches extends PaginatedCollection<VSwitch> {
+
+ @ConstructorProperties({ "VSwitches", "PageNumber", "TotalCount", "PageSize", "RegionId", "RequestId" })
+ public VSwitches(Map<String, Iterable<VSwitch>> content, Integer pageNumber, Integer totalCount, Integer pageSize, String regionId, String requestId) {
+ super(content, pageNumber, totalCount, pageSize, regionId, requestId);
+ }
+ }
+ @Inject
+ ParseVSwitches(final Json json) {
+ super(json, TypeLiteral.get(VSwitches.class));
+ }
+
+ static class ToPagedIterable extends ArgsToPagedIterable<VSwitch, ParseVSwitches.ToPagedIterable> {
+
+ private final ECSComputeServiceApi api;
+
+ @Inject
+ ToPagedIterable(ECSComputeServiceApi api) {
+ this.api = api;
+ }
+
+ @Override
+ protected Function<Object, IterableWithMarker<VSwitch>> markerToNextForArgs(List<Object> args) {
+ if (args == null || args.isEmpty()) throw new IllegalStateException("Can't advance the PagedIterable");
+ final String regionId = args.get(0).toString();
+ final ListVSwitchesOptions original = (ListVSwitchesOptions) Iterables.tryFind(args, Predicates.instanceOf(ListVSwitchesOptions.class)).orNull();
+
+ return new Function<Object, IterableWithMarker<VSwitch>>() {
+ @Override
+ public IterableWithMarker<VSwitch> apply(Object input) {
+ ListVSwitchesOptions options = original == null ?
+ ListVSwitchesOptions.Builder.paginationOptions(PaginationOptions.class.cast(input)) :
+ original.paginationOptions(PaginationOptions.class.cast(input));
+ return api.vSwitchApi().list(regionId, options);
+ }
+ };
+ }
+ }
+ }
+
+ @Named("vswitch:create")
+ @POST
+ @QueryParams(keys = "Action", values = "CreateVSwitch")
+ VSwitchRequest create(@QueryParam("ZoneId") String zone,
+ @QueryParam("CidrBlock") String cidrBlock,
+ @QueryParam("VpcId") String vpcId);
+
+ @Named("vswitch:create")
+ @POST
+ @QueryParams(keys = "Action", values = "CreateVSwitch")
+ VSwitchRequest create(@QueryParam("ZoneId") String zone,
+ @QueryParam("CidrBlock") String cidrBlock,
+ @QueryParam("VpcId") String vpcId,
+ CreateVSwitchOptions vSwitchOptions);
+
+ @Named("vswitch:delete")
+ @POST
+ @QueryParams(keys = "Action", values = "DeleteVSwitch")
+ Request delete(@QueryParam("RegionId") String region,
+ @QueryParam("VSwitchId") String vSwitchId);
+}
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/functions/PutStringInDoubleQuotes.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/functions/PutStringInDoubleQuotes.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/functions/PutStringInDoubleQuotes.java
new file mode 100644
index 0000000..98efc8d
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/functions/PutStringInDoubleQuotes.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.functions;
+
+import com.google.common.base.Function;
+
+public class PutStringInDoubleQuotes implements Function<String, String> {
+
+ @Override
+ public String apply(String input) {
+ return new StringBuilder(input.length() + 1).append('"').append(input).append('"').toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/handlers/ECSErrorRetryHandler.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/handlers/ECSErrorRetryHandler.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/handlers/ECSErrorRetryHandler.java
new file mode 100644
index 0000000..0a32145
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/handlers/ECSErrorRetryHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.handlers;
+
+import com.google.inject.Inject;
+import org.jclouds.aliyun.ecs.domain.ErrorMessage;
+import org.jclouds.http.HttpCommand;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.HttpRetryHandler;
+import org.jclouds.http.HttpUtils;
+import org.jclouds.http.annotation.ClientError;
+import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
+import org.jclouds.json.Json;
+
+import java.io.ByteArrayInputStream;
+import java.util.Set;
+
+import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
+
+/**
+ * Handles Retryable responses with error codes in the 4xx range
+ */
+public class ECSErrorRetryHandler implements HttpRetryHandler {
+
+ private final Json json;
+ private final BackoffLimitedRetryHandler backoffLimitedRetryHandler;
+ private final Set<String> retryableCodes;
+
+ @Inject
+ public ECSErrorRetryHandler(Json json, BackoffLimitedRetryHandler backoffLimitedRetryHandler,
+ @ClientError Set<String> retryableCodes) {
+ this.json = json;
+ this.backoffLimitedRetryHandler = backoffLimitedRetryHandler;
+ this.retryableCodes = retryableCodes;
+ }
+
+ @Override
+ public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
+ byte[] content = HttpUtils.closeClientButKeepContentStream(response);
+
+ if (response.getStatusCode() == 400 || response.getStatusCode() == 403 || response.getStatusCode() == 409) {
+ // Content can be null in the case of HEAD requests
+ if (response.getPayload() != null) {
+ closeClientButKeepContentStream(response);
+ ErrorMessage error = json.fromJson(new ByteArrayInputStream(content), ErrorMessage.class);
+ if (error != null) {
+ return shouldRetryRequestOnError(command, response, error);
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean shouldRetryRequestOnError(HttpCommand command, HttpResponse response, ErrorMessage error) {
+ if (retryableCodes.contains(error.code()))
+ return backoffLimitedRetryHandler.shouldRetryRequest(command, response);
+ return false;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/predicates/InstanceStatusPredicate.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/predicates/InstanceStatusPredicate.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/predicates/InstanceStatusPredicate.java
new file mode 100644
index 0000000..9a42261
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/predicates/InstanceStatusPredicate.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.predicates;
+
+import com.google.common.base.Predicate;
+import org.jclouds.aliyun.ecs.domain.InstanceStatus;
+
+public class InstanceStatusPredicate implements Predicate<InstanceStatus> {
+ private final String instanceId;
+
+ public InstanceStatusPredicate(String instanceId) {
+ this.instanceId = instanceId;
+ }
+
+ @Override
+ public boolean apply(InstanceStatus instanceStatus) {
+ return instanceStatus.instanceId().equalsIgnoreCase(instanceId);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceLiveTest.java b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceLiveTest.java
new file mode 100644
index 0000000..74e635c
--- /dev/null
+++ b/aliyun-ecs/src/test/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceLiveTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Module;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceLiveTest;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.Test;
+
+/**
+ * Live tests for the {@link org.jclouds.compute.ComputeService} integration.
+ */
+@Test(groups = "live", singleThreaded = true, testName = "ECSComputeServiceLiveTest")
+public class ECSComputeServiceLiveTest extends BaseComputeServiceLiveTest {
+
+ public ECSComputeServiceLiveTest() {
+ provider = "alibaba-ecs";
+ }
+
+ @Override
+ protected Module getSshModule() {
+ return new SshjSshClientModule();
+ }
+
+ @Override
+ protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
+ // The ECS API does not return the user data
+ }
+
+}
[2/7] jclouds-labs git commit: [JCLOUDS-1430] Aliyun ECS
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/test/resources/instanceTypes.json
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/test/resources/instanceTypes.json b/aliyun-ecs/src/test/resources/instanceTypes.json
new file mode 100644
index 0000000..7a9a81a
--- /dev/null
+++ b/aliyun-ecs/src/test/resources/instanceTypes.json
@@ -0,0 +1,4281 @@
+{
+ "InstanceTypes": {
+ "InstanceType": [
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.t1",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t1.xsmall",
+ "GPUSpec": "",
+ "MemorySize": 0.5,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.t1",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t1.small",
+ "GPUSpec": "",
+ "MemorySize": 1.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.s2",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.s2.small",
+ "GPUSpec": "",
+ "MemorySize": 2.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.s3",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.s3.medium",
+ "GPUSpec": "",
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.c1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.c1.small",
+ "GPUSpec": "",
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.c2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.c2.medium",
+ "GPUSpec": "",
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.s1",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.s1.small",
+ "GPUSpec": "",
+ "MemorySize": 2.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.s2",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.s2.large",
+ "GPUSpec": "",
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.s3",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.s3.large",
+ "GPUSpec": "",
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.c1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.c1.large",
+ "GPUSpec": "",
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.c2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.c2.large",
+ "GPUSpec": "",
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.s1",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.s1.medium",
+ "GPUSpec": "",
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.s2",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.s2.xlarge",
+ "GPUSpec": "",
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.m1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.m1.medium",
+ "GPUSpec": "",
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.m1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.m1.xlarge",
+ "GPUSpec": "",
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.c2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.c2.xlarge",
+ "GPUSpec": "",
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.s1",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.s1.large",
+ "GPUSpec": "",
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.s2",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.s2.2xlarge",
+ "GPUSpec": "",
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.m2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.m2.medium",
+ "GPUSpec": "",
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.m2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.m2.xlarge",
+ "GPUSpec": "",
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.n1",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.n1.tiny",
+ "GPUSpec": "",
+ "MemorySize": 1.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.n1",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.n1.small",
+ "GPUSpec": "",
+ "MemorySize": 2.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.n1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n1.medium",
+ "GPUSpec": "",
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.n1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n1.large",
+ "GPUSpec": "",
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.n1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n1.xlarge",
+ "GPUSpec": "",
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.n1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n1.3xlarge",
+ "GPUSpec": "",
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.n1",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n1.7xlarge",
+ "GPUSpec": "",
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.n2",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.n2.small",
+ "GPUSpec": "",
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.n2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n2.medium",
+ "GPUSpec": "",
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.n2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n2.large",
+ "GPUSpec": "",
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.n2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n2.xlarge",
+ "GPUSpec": "",
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.n2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n2.3xlarge",
+ "GPUSpec": "",
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.n2",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n2.7xlarge",
+ "GPUSpec": "",
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.e3",
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.e3.small",
+ "GPUSpec": "",
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.e3",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.e3.medium",
+ "GPUSpec": "",
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.e3",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.e3.large",
+ "GPUSpec": "",
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.e3",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.e3.xlarge",
+ "GPUSpec": "",
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.e3",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.e3.3xlarge",
+ "GPUSpec": "",
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.e3",
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.e3.7xlarge",
+ "GPUSpec": "",
+ "MemorySize": 256.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.sn1",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.sn1.medium",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.sn2",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.sn2.medium",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.sn1",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 200000,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.sn1.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.sn1",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.sn1.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.sn1",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn1.3xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.sn1",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn1.7xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.sn2",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 200000,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.sn2.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.sn2",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.sn2.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.sn2",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn2.3xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.sn2",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn2.7xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.n4",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 50000,
+ "InstancePpsTx": 50000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.n4.small",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 2.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.n4",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.n4.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.n4",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 150000,
+ "InstancePpsTx": 150000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n4.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.n4",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n4.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.n4",
+ "InstanceBandwidthRx": 2560000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n4.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2560000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.n4",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.n4.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.mn4",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 50000,
+ "InstancePpsTx": 50000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.mn4.small",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.mn4",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.mn4.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.mn4",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 150000,
+ "InstancePpsTx": 150000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.mn4.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.mn4",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.mn4.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.mn4",
+ "InstanceBandwidthRx": 2560000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.mn4.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2560000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.mn4",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.mn4.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.xn4",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 50000,
+ "InstancePpsTx": 50000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.xn4.small",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 1.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.e4",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.e4.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.e4",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 150000,
+ "InstancePpsTx": 150000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.e4.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.e4",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.e4.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.e4",
+ "InstanceBandwidthRx": 2560000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.e4.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2560000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 12,
+ "InstanceTypeFamily": "ecs.gn3",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 200000,
+ "LocalStorageCapacity": 350,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.gn3.2xlarge",
+ "GPUSpec": "NVidia K2",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 24.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.sn2",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1200000,
+ "InstancePpsTx": 1200000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn2.13xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 224.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.e4",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 50000,
+ "InstancePpsTx": 50000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.e4.small",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.se1",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.se1.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.se1",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 200000,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.se1.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.se1",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.se1.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.se1",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.se1.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.se1",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.se1.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 256.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.se1",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1200000,
+ "InstancePpsTx": 1200000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.se1.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 480.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.ga1",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 500000,
+ "LocalStorageCapacity": 350,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.ga1.4xlarge",
+ "GPUSpec": "AMD S7150",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 40.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.ga1",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "LocalStorageCapacity": 700,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.ga1.8xlarge",
+ "GPUSpec": "AMD S7150",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 80.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.ga1",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1200000,
+ "LocalStorageCapacity": 1400,
+ "InstancePpsTx": 1200000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.ga1.14xlarge",
+ "GPUSpec": "AMD S7150",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 160.0,
+ "GPUAmount": 4,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.gn4",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn4.8xlarge",
+ "GPUSpec": "NVIDIA M40",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 48.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.gn4",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1200000,
+ "InstancePpsTx": 1200000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn4.14xlarge",
+ "GPUSpec": "NVIDIA M40",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 96.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.i1",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 200000,
+ "LocalStorageCapacity": 104,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.i1.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.i1",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 400000,
+ "LocalStorageCapacity": 208,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.i1.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.i1",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 500000,
+ "LocalStorageCapacity": 416,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i1.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.i1",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "LocalStorageCapacity": 832,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i1.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.i1",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1200000,
+ "LocalStorageCapacity": 1456,
+ "InstancePpsTx": 1200000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i1.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 224.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.cm4",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 200000,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.cm4.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.cm4",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.cm4.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.cm4",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.cm4.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.ce4",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 200000,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.ce4.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.c4",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 200000,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.c4.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.c4",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.c4.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.c4",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.c4.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.cm4",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1200000,
+ "InstancePpsTx": 1200000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.cm4.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 96.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.sc1",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sc1.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 4,
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.d1",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 300000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.d1.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 8,
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.d1",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 600000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 600000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 12,
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.d1",
+ "InstanceBandwidthRx": 8192000,
+ "InstancePpsRx": 800000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 8192000,
+ "MemorySize": 96.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 16,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.d1",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1000000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 28,
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.d1",
+ "InstanceBandwidthRx": 17408000,
+ "InstancePpsRx": 1800000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 1800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 17408000,
+ "MemorySize": 224.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.ga1",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 300000,
+ "LocalStorageCapacity": 175,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.ga1.2xlarge",
+ "GPUSpec": "AMD S7150/2",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 20.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.ga1",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 200000,
+ "LocalStorageCapacity": 87,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.ga1.xlarge",
+ "GPUSpec": "AMD S7150/4",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 10.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.sn1ne",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.sn1ne.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.sn1ne",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.sn1ne.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.sn1ne",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.sn1ne.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.sn1ne",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 1600000,
+ "InstancePpsTx": 1600000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn1ne.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.sn1ne",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 2500000,
+ "InstancePpsTx": 2500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn1ne.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.sn2ne",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.sn2ne.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.sn2ne",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.sn2ne.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.sn2ne",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.sn2ne.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.sn2ne",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 1600000,
+ "InstancePpsTx": 1600000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn2ne.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.sn2ne",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 2500000,
+ "InstancePpsTx": 2500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn2ne.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.sn2ne",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.sn2ne.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 224.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.se1ne",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.se1ne.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.se1ne",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.se1ne.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.se1ne",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.se1ne.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.se1ne",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 1600000,
+ "InstancePpsTx": 1600000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.se1ne.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.se1ne",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 2500000,
+ "InstancePpsTx": 2500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.se1ne.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 256.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.se1ne",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.se1ne.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 480.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.i1",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 800000,
+ "LocalStorageCapacity": 1456,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i1-c10d1.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.i1",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 400000,
+ "LocalStorageCapacity": 1456,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i1-c5d1.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.f1",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.f1-c8f1.2xlarge",
+ "GPUSpec": "INTEL ARRIA 10 GX 1150",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 60.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 300000,
+ "LocalStorageCapacity": 440,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.gn5-c4g1.xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 30.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 400000,
+ "LocalStorageCapacity": 440,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.gn5-c8g1.2xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 60.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 1000000,
+ "LocalStorageCapacity": 880,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.gn5-c4g1.2xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 60.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 1000000,
+ "LocalStorageCapacity": 880,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5-c8g1.4xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 120.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 2000000,
+ "LocalStorageCapacity": 1760,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5-c8g1.8xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 240.0,
+ "GPUAmount": 4,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 54,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 25600000,
+ "InstancePpsRx": 4000000,
+ "LocalStorageCapacity": 1760,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5-c8g1.14xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 25600000,
+ "MemorySize": 480.0,
+ "GPUAmount": 8,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.gn4",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.gn4-c4g1.xlarge",
+ "GPUSpec": "NVIDIA M40",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 30.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.gn4",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.gn4-c8g1.2xlarge",
+ "GPUSpec": "NVIDIA M40",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 30.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.gn4",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.gn4-c4g1.2xlarge",
+ "GPUSpec": "NVIDIA M40",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 60.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.gn4",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn4-c8g1.4xlarge",
+ "GPUSpec": "NVIDIA M40",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 60.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 4,
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.d1ne",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 1000000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.d1ne.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 8,
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.d1ne",
+ "InstanceBandwidthRx": 12288000,
+ "InstancePpsRx": 1600000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 1600000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1ne.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 12288000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 12,
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.d1ne",
+ "InstanceBandwidthRx": 16384000,
+ "InstancePpsRx": 2000000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1ne.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 16384000,
+ "MemorySize": 96.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 16,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.d1ne",
+ "InstanceBandwidthRx": 20480000,
+ "InstancePpsRx": 2500000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 2500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1ne.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 20480000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 28,
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.d1ne",
+ "InstanceBandwidthRx": 35840000,
+ "InstancePpsRx": 4500000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1ne.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 35840000,
+ "MemorySize": 224.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 12,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.d1",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 1000000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1-c8d3.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "LocalStorageAmount": 12,
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.d1",
+ "InstanceBandwidthRx": 17408000,
+ "InstancePpsRx": 1400000,
+ "LocalStorageCapacity": 5500,
+ "InstancePpsTx": 1400000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.d1-c14d3.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 17408000,
+ "MemorySize": 160.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_hdd_pro"
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.c5",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.c5.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.c5",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.c5.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.c5",
+ "InstanceBandwidthRx": 2560000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.c5.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2560000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.c5",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.c5.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.c5",
+ "InstanceBandwidthRx": 7680000,
+ "InstancePpsRx": 1500000,
+ "InstancePpsTx": 1500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.c5.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 7680000,
+ "MemorySize": 48.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.c5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.c5.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 64,
+ "InstanceTypeFamily": "ecs.c5",
+ "InstanceBandwidthRx": 20480000,
+ "InstancePpsRx": 4000000,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.c5.16xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 20480000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.g5",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.g5.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.g5",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.g5.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.g5",
+ "InstanceBandwidthRx": 2560000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.g5.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2560000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.g5",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.g5.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.g5",
+ "InstanceBandwidthRx": 7680000,
+ "InstancePpsRx": 1500000,
+ "InstancePpsTx": 1500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.g5.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 7680000,
+ "MemorySize": 96.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.g5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.g5.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 64,
+ "InstanceTypeFamily": "ecs.g5",
+ "InstanceBandwidthRx": 20480000,
+ "InstancePpsRx": 4000000,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.g5.16xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 20480000,
+ "MemorySize": 256.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.r5.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.r5.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 2560000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.r5.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2560000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.r5.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 7680000,
+ "InstancePpsRx": 1500000,
+ "InstancePpsTx": 1500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.r5.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 7680000,
+ "MemorySize": 192.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.r5.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 256.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 64,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 20480000,
+ "InstancePpsRx": 4000000,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.r5.16xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 20480000,
+ "MemorySize": 512.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 88,
+ "InstanceTypeFamily": "ecs.r5",
+ "InstanceBandwidthRx": 30720000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 15,
+ "InstanceTypeId": "ecs.r5.22xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 30720000,
+ "MemorySize": 704.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.hfc5",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.hfc5.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.hfc5",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.hfc5.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.hfc5",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.hfc5.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.hfc5",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 1600000,
+ "InstancePpsTx": 1600000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.hfc5.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.hfc5",
+ "InstanceBandwidthRx": 4608000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.hfc5.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 4608000,
+ "MemorySize": 48.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.hfc5",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 2500000,
+ "InstancePpsTx": 2500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.hfc5.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.hfg5",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 300000,
+ "InstancePpsTx": 300000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.hfg5.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.hfg5",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 500000,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.hfg5.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.hfg5",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 1000000,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.hfg5.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.hfg5",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 1600000,
+ "InstancePpsTx": 1600000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.hfg5.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 24,
+ "InstanceTypeFamily": "ecs.hfg5",
+ "InstanceBandwidthRx": 4608000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.hfg5.6xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 4608000,
+ "MemorySize": 96.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.hfg5",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 2500000,
+ "InstancePpsTx": 2500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.hfg5.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.hfg5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4000000,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.hfg5.14xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 160.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.i2",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 500000,
+ "LocalStorageCapacity": 894,
+ "InstancePpsTx": 500000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.i2.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.i2",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 1000000,
+ "LocalStorageCapacity": 1788,
+ "InstancePpsTx": 1000000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.i2.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 64.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 2,
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.i2",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 1500000,
+ "LocalStorageCapacity": 1788,
+ "InstancePpsTx": 1500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i2.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 128.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 4,
+ "CpuCoreCount": 32,
+ "InstanceTypeFamily": "ecs.i2",
+ "InstanceBandwidthRx": 6144000,
+ "InstancePpsRx": 2000000,
+ "LocalStorageCapacity": 1788,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i2.8xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 6144000,
+ "MemorySize": 256.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 8,
+ "CpuCoreCount": 64,
+ "InstanceTypeFamily": "ecs.i2",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4000000,
+ "LocalStorageCapacity": 1788,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.i2.16xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 512.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 28,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 2250000,
+ "LocalStorageCapacity": 440,
+ "InstancePpsTx": 2250000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5-c28g1.7xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 112.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "LocalStorageAmount": 1,
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.gn5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "LocalStorageCapacity": 880,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5-c28g1.14xlarge",
+ "GPUSpec": "NVIDIA P100",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 224.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": "local_ssd_pro"
+ },
+ {
+ "CpuCoreCount": 80,
+ "InstanceTypeFamily": "ecs.re4",
+ "InstanceBandwidthRx": 15360000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.re4.20xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 15360000,
+ "MemorySize": 960.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 160,
+ "InstanceTypeFamily": "ecs.re4",
+ "InstanceBandwidthRx": 30720000,
+ "InstancePpsRx": 4000000,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.re4.40xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 30720000,
+ "MemorySize": 1920.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.gn5i",
+ "InstanceBandwidthRx": 1024000,
+ "InstancePpsRx": 100000,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.gn5i-c2g1.large",
+ "GPUSpec": "Nvidia Tesla P4",
+ "InstanceBandwidthTx": 1024000,
+ "MemorySize": 8.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.gn5i",
+ "InstanceBandwidthRx": 1536000,
+ "InstancePpsRx": 200000,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 3,
+ "InstanceTypeId": "ecs.gn5i-c4g1.xlarge",
+ "GPUSpec": "Nvidia Tesla P4",
+ "InstanceBandwidthTx": 1536000,
+ "MemorySize": 16.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.gn5i",
+ "InstanceBandwidthRx": 2048000,
+ "InstancePpsRx": 400000,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 4,
+ "InstanceTypeId": "ecs.gn5i-c8g1.2xlarge",
+ "GPUSpec": "Nvidia Tesla P4",
+ "InstanceBandwidthTx": 2048000,
+ "MemorySize": 32.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.gn5i",
+ "InstanceBandwidthRx": 3072000,
+ "InstancePpsRx": 800000,
+ "InstancePpsTx": 800000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5i-c16g1.4xlarge",
+ "GPUSpec": "Nvidia Tesla P4",
+ "InstanceBandwidthTx": 3072000,
+ "MemorySize": 64.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.gn5i",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5i-c28g1.14xlarge",
+ "GPUSpec": "Nvidia Tesla P4",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 224.0,
+ "GPUAmount": 2,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 28,
+ "InstanceTypeFamily": "ecs.gn5t",
+ "InstanceBandwidthRx": 13312000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5t.7xlarge",
+ "GPUSpec": "Nvidia GPU",
+ "InstanceBandwidthTx": 13312000,
+ "MemorySize": 112.0,
+ "GPUAmount": 4,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 56,
+ "InstanceTypeFamily": "ecs.gn5t",
+ "InstanceBandwidthRx": 25600000,
+ "InstancePpsRx": 4000000,
+ "InstancePpsTx": 4000000,
+ "EniQuantity": 8,
+ "InstanceTypeId": "ecs.gn5t.14xlarge",
+ "GPUSpec": "Nvidia GPU",
+ "InstanceBandwidthTx": 25600000,
+ "MemorySize": 224.0,
+ "GPUAmount": 8,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InitialCredit": 180,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-c1m1.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 2.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 30
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 200000,
+ "InitialCredit": 360,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m1.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 60
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 400000,
+ "InitialCredit": 720,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m1.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 120
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 600000,
+ "InitialCredit": 1440,
+ "InstancePpsTx": 600000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m1.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 240
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InitialCredit": 180,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-c1m2.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 30
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 200000,
+ "InitialCredit": 360,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m2.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 60
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 400000,
+ "InitialCredit": 720,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m2.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 120
+ },
+ {
+ "CpuCoreCount": 16,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 600000,
+ "InitialCredit": 1440,
+ "InstancePpsTx": 600000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m2.4xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 240
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 512000,
+ "InstancePpsRx": 100000,
+ "InitialCredit": 180,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-c1m4.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 512000,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 30
+ },
+ {
+ "CpuCoreCount": 4,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 819200,
+ "InstancePpsRx": 200000,
+ "InitialCredit": 360,
+ "InstancePpsTx": 200000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m4.xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 819200,
+ "MemorySize": 16.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 60
+ },
+ {
+ "CpuCoreCount": 8,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 1228800,
+ "InstancePpsRx": 400000,
+ "InitialCredit": 720,
+ "InstancePpsTx": 400000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.t5-c1m4.2xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 1228800,
+ "MemorySize": 32.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 120
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 102400,
+ "InstancePpsRx": 40000,
+ "InitialCredit": 90,
+ "InstancePpsTx": 40000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-lc2m1.nano",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 102400,
+ "MemorySize": 0.5,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 10
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 204800,
+ "InstancePpsRx": 60000,
+ "InitialCredit": 90,
+ "InstancePpsTx": 60000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-lc1m1.small",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 204800,
+ "MemorySize": 1.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 10
+ },
+ {
+ "CpuCoreCount": 1,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 204800,
+ "InstancePpsRx": 60000,
+ "InitialCredit": 90,
+ "InstancePpsTx": 60000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-lc1m2.small",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 204800,
+ "MemorySize": 2.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 10
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 409600,
+ "InstancePpsRx": 100000,
+ "InitialCredit": 180,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-lc1m2.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 409600,
+ "MemorySize": 4.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 20
+ },
+ {
+ "CpuCoreCount": 2,
+ "InstanceTypeFamily": "ecs.t5",
+ "InstanceBandwidthRx": 409600,
+ "InstancePpsRx": 100000,
+ "InitialCredit": 180,
+ "InstancePpsTx": 100000,
+ "EniQuantity": 1,
+ "InstanceTypeId": "ecs.t5-lc1m4.large",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 409600,
+ "MemorySize": 8.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": "",
+ "BaselineCredit": 20
+ },
+ {
+ "CpuCoreCount": 28,
+ "InstanceTypeFamily": "ecs.f1",
+ "InstanceBandwidthRx": 5120000,
+ "InstancePpsRx": 2000000,
+ "InstancePpsTx": 2000000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.f1-c28f1.7xlarge",
+ "GPUSpec": "INTEL ARRIA 10 GX 1150",
+ "InstanceBandwidthTx": 5120000,
+ "MemorySize": 112.0,
+ "GPUAmount": 1,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 96,
+ "InstanceTypeFamily": "ecs.sccg5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 32,
+ "InstanceTypeId": "ecs.sccg5.24xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 384.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 64,
+ "InstanceTypeFamily": "ecs.scch5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 32,
+ "InstanceTypeId": "ecs.scch5.16xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 192.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 64,
+ "InstanceTypeFamily": "ecs.sccgn5d",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.sccgn5d.16xlarge",
+ "GPUSpec": "Nvidia GTX 1080Ti",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 256.0,
+ "GPUAmount": 8,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 64,
+ "InstanceTypeFamily": "ecs.sccgn5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 2,
+ "InstanceTypeId": "ecs.sccgn5.16xlarge",
+ "GPUSpec": "Nvidia P100",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 512.0,
+ "GPUAmount": 8,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 96,
+ "InstanceTypeFamily": "ecs.ebmg5",
+ "InstanceBandwidthRx": 10240000,
+ "InstancePpsRx": 4500000,
+ "InstancePpsTx": 4500000,
+ "EniQuantity": 32,
+ "InstanceTypeId": "ecs.ebmg5.24xlarge",
+ "GPUSpec": "",
+ "InstanceBandwidthTx": 10240000,
+ "MemorySize": 384.0,
+ "GPUAmount": 0,
+ "LocalStorageCategory": ""
+ },
+ {
+ "CpuCoreCount": 96,
+ "InstanceTypeFamily": "e
<TRUNCATED>
[6/7] jclouds-labs git commit: [JCLOUDS-1430] Aliyun ECS
Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodes.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodes.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodes.java
new file mode 100644
index 0000000..8d302a2
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CreateResourcesThenCreateNodes.java
@@ -0,0 +1,360 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.strategy;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import org.jclouds.Constants;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.compute.options.ECSServiceTemplateOptions;
+import org.jclouds.aliyun.ecs.domain.IpProtocol;
+import org.jclouds.aliyun.ecs.domain.KeyPair;
+import org.jclouds.aliyun.ecs.domain.KeyPairRequest;
+import org.jclouds.aliyun.ecs.domain.SecurityGroup;
+import org.jclouds.aliyun.ecs.domain.SecurityGroupRequest;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.VPCRequest;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.VSwitchRequest;
+import org.jclouds.aliyun.ecs.domain.Zone;
+import org.jclouds.aliyun.ecs.domain.options.CreateSecurityGroupOptions;
+import org.jclouds.aliyun.ecs.domain.options.CreateVPCOptions;
+import org.jclouds.aliyun.ecs.domain.options.CreateVSwitchOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions;
+import org.jclouds.aliyun.ecs.domain.options.TagOptions;
+import org.jclouds.compute.config.CustomizationResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodeWithGroupEncodedIntoName;
+import org.jclouds.compute.strategy.CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.impl.CreateNodesWithGroupEncodedIntoNameThenAddToSet;
+import org.jclouds.logging.Logger;
+import org.jclouds.ssh.SshKeys;
+
+import javax.annotation.Nullable;
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PublicKey;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.RSAPublicKeySpec;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.collect.Iterables.get;
+import static com.google.common.collect.Iterables.size;
+import static org.jclouds.aliyun.ecs.domain.ResourceType.SECURITYGROUP;
+import static org.jclouds.compute.util.ComputeServiceUtils.getPortRangesFromList;
+
+@Singleton
+public class CreateResourcesThenCreateNodes extends CreateNodesWithGroupEncodedIntoNameThenAddToSet {
+
+ public static final String INTERNET = "0.0.0.0/0";
+ public static final String DEFAULT_CIDR_BLOCK = "172.16.1.0/24";
+ public static final String JCLOUDS_KEYPAIR_IMPORTED = "jclouds-imported";
+ public static final String PORT_RANGE_FORMAT = "%d/%d";
+ protected static final String DEFAULT_DESCRIPTION_SUFFIX = "created by jclouds";
+ protected static final String VSWITCH_PREFIX = "vswitch";
+ protected static final String VPC_PREFIX = "vpc";
+
+ private final ECSComputeServiceApi api;
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ protected CreateResourcesThenCreateNodes(CreateNodeWithGroupEncodedIntoName addNodeWithGroupStrategy,
+ ListNodesStrategy listNodesStrategy, GroupNamingConvention.Factory namingConvention,
+ @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+ CustomizeNodeAndAddToGoodMapOrPutExceptionIntoBadMap.Factory customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory,
+ ECSComputeServiceApi api) {
+ super(addNodeWithGroupStrategy, listNodesStrategy, namingConvention, userExecutor,
+ customizeNodeAndAddToGoodMapOrPutExceptionIntoBadMapFactory);
+ this.api = api;
+ }
+
+ @Override
+ public Map<?, ListenableFuture<Void>> execute(String group, int count, Template template,
+ Set<NodeMetadata> goodNodes, Map<NodeMetadata, Exception> badNodes,
+ Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
+
+ String regionId = template.getLocation().getId();
+ ECSServiceTemplateOptions options = template.getOptions().as(ECSServiceTemplateOptions.class);
+
+ Optional<SecurityGroup> securityGroupOptional = tryFindSecurityGroupInRegion(regionId, options.getGroups());
+
+ String vpcIdFromSecurityGroup;
+ String vpcId;
+
+ if (securityGroupOptional.isPresent()) {
+ vpcIdFromSecurityGroup = securityGroupOptional.get().vpcId();
+ if (!Strings.isNullOrEmpty(options.getVSwitchId())) {
+ validateVSwitchId(regionId, options.getVSwitchId(), securityGroupOptional.get().name(), vpcIdFromSecurityGroup);
+ } else {
+ String message = String.format("Security group (%s) belongs to VPC (%s). Please specify a vSwitch Id of that VPC (%s) using ECSServiceTemplateOptions.vSwitchId",
+ securityGroupOptional.get().name(),
+ vpcIdFromSecurityGroup,
+ vpcIdFromSecurityGroup);
+ throw new IllegalStateException(message);
+ }
+ } else {
+ if (!Strings.isNullOrEmpty(options.getVSwitchId())) {
+ VSwitch vSwitch = tryFindVSwitch(regionId, options.getVSwitchId());
+ vpcId = vSwitch.vpcId();
+ } else {
+ vpcId = createDefaultVPC(regionId, group);
+ String vSwitchId = createDefaultVSwitch(regionId, vpcId, group);
+ options.vSwitchId(vSwitchId);
+ }
+ String createdSecurityGroupId = createSecurityGroupForOptions(group, regionId, vpcId, options);
+ options.securityGroups(createdSecurityGroupId);
+ }
+
+
+ // If keys haven't been configured, generate a key pair
+ if (Strings.isNullOrEmpty(options.getPublicKey()) &&
+ Strings.isNullOrEmpty(options.getLoginPrivateKey())) {
+ String uniqueNameForGroup = namingConvention.create().uniqueNameForGroup(group);
+ KeyPairRequest keyPairRequest = generateKeyPair(regionId, uniqueNameForGroup);
+ options.keyPairName(keyPairRequest.getKeyPairName());
+ options.overrideLoginPrivateKey(keyPairRequest.getPrivateKeyBody());
+ }
+
+ // If there is a script to run in the node, make sure a private key has
+ // been configured so jclouds will be able to access the node
+ if (options.getRunScript() != null && Strings.isNullOrEmpty(options.getLoginPrivateKey())) {
+ logger.warn(">> A runScript has been configured but no SSH key has been provided. Authentication will delegate to the ssh-agent");
+ }
+
+ // If there is a public key configured, then make sure there is a key pair for it
+ if (!Strings.isNullOrEmpty(options.getPublicKey())) {
+ KeyPair keyPair = getOrImportKeyPairForPublicKey(options, regionId);
+ options.keyPairName(keyPair.name());
+ }
+
+ Map<?, ListenableFuture<Void>> responses = super.execute(group, count, template, goodNodes, badNodes, customizationResponses);
+
+ // Key pairs are only required to create the devices.
+ // Better to delete the auto-generated key pairs when they are mo more required
+ registerAutoGeneratedKeyPairCleanupCallbacks(responses, regionId, options.getKeyPairName());
+
+ return responses;
+ }
+
+ private void validateVSwitchId(String regionId,
+ String vSwitchId,
+ String securityGroupName,
+ String vpcIdFromSecurityGroup) {
+ Optional<VSwitch> optionalVSwitch = tryFindVSwitchInVPC(regionId, vpcIdFromSecurityGroup, vSwitchId);
+ if (!optionalVSwitch.isPresent()) {
+ String message = String.format("security group (%s) and vSwitch (%s) must be in the same VPC_PREFIX (%s)",
+ securityGroupName,
+ optionalVSwitch.get().name(),
+ vpcIdFromSecurityGroup);
+
+ throw new IllegalStateException(message);
+ }
+ }
+
+ private String createDefaultVPC(String regionId, String group) {
+ String vpcName = String.format("%s-%s", VPC_PREFIX, group);
+ VPCRequest vpcRequest = api.vpcApi().create(regionId, CreateVPCOptions.Builder.vpcName(vpcName).description(String.format("%s - %s", VPC_PREFIX, DEFAULT_DESCRIPTION_SUFFIX)));
+ return vpcRequest.getVpcId();
+ }
+
+ private String createDefaultVSwitch(String regionId, String vpcId, String name) {
+ String vSwitchName = String.format("%s-%s", VSWITCH_PREFIX, name);
+ Zone zone = Iterables.getFirst(api.regionAndZoneApi().describeZones(regionId), null);
+ VSwitchRequest vSwitchRequest = api.vSwitchApi().create(zone.id(), DEFAULT_CIDR_BLOCK, vpcId,
+ CreateVSwitchOptions.Builder.vSwitchName(vSwitchName).description(String.format("%s - %s", vSwitchName, DEFAULT_DESCRIPTION_SUFFIX)));
+ return vSwitchRequest.getVSwitchId();
+ }
+
+ private KeyPair getOrImportKeyPairForPublicKey(ECSServiceTemplateOptions options, String regionId) {
+ logger.debug(">> checking if the key pair already exists...");
+ PublicKey userKey = readPublicKey(options.getPublicKey());
+ final String fingerprint = computeFingerprint(userKey);
+ KeyPair keyPair;
+
+ synchronized (CreateResourcesThenCreateNodes.class) {
+ Optional<KeyPair> keyPairOptional = Iterables
+ .tryFind(api.sshKeyPairApi().list(regionId).concat(), new Predicate<KeyPair>() {
+ @Override
+ public boolean apply(KeyPair input) {
+ return input.keyPairFingerPrint().equals(fingerprint.replace(":", ""));
+ }
+ });
+ if (!keyPairOptional.isPresent()) {
+ logger.debug(">> key pair not found. Importing a new key pair %s ...", fingerprint);
+ keyPair = api.sshKeyPairApi().importKeyPair(
+ regionId,
+ options.getPublicKey(),
+ namingConvention.create().uniqueNameForGroup(JCLOUDS_KEYPAIR_IMPORTED));
+ logger.debug(">> key pair imported! %s", keyPair);
+ } else {
+ logger.debug(">> key pair found for key %s", fingerprint);
+ keyPair = keyPairOptional.get();
+ }
+ return keyPair;
+ }
+ }
+
+ private KeyPairRequest generateKeyPair(String regionId, String uniqueNameForGroup) {
+ logger.debug(">> creating default keypair for node...");
+ KeyPairRequest keyPairRequest = api.sshKeyPairApi().create(regionId, uniqueNameForGroup);
+ logger.debug(">> keypair created! %s", keyPairRequest);
+ return keyPairRequest;
+ }
+
+ private Optional<SecurityGroup> tryFindSecurityGroupInRegion(String regionId, final Set<String> securityGroups) {
+ checkArgument(securityGroups.size() <= 1, "Only one security group can be configured for each network interface");
+ final String securityGroupId = Iterables.get(securityGroups, 0, null);
+
+ if (securityGroupId != null) {
+ return api.securityGroupApi().list(regionId).concat().firstMatch(new Predicate<SecurityGroup>() {
+ @Override
+ public boolean apply(@Nullable SecurityGroup input) {
+ return securityGroupId.equals(input.id());
+ }
+ });
+ }
+ return Optional.absent();
+ }
+
+ private VSwitch tryFindVSwitch(String regionId, String vSwitchId) {
+ ListVSwitchesOptions listVSwitchesOptions = ListVSwitchesOptions.Builder.vSwitchId(vSwitchId);
+ Optional<VSwitch> optionalVSwitch = api.vSwitchApi().list(regionId, listVSwitchesOptions).first();
+ if (!optionalVSwitch.isPresent()) {
+ String message = String.format("Cannot find a valid vSwitch with id (%s) within region (%s)",
+ vSwitchId,
+ regionId);
+ throw new IllegalStateException(message);
+ }
+ return optionalVSwitch.get();
+ }
+
+ private Optional<VSwitch> tryFindVSwitchInVPC(String regionId, String vpcId, String vSwitchId) {
+ ListVSwitchesOptions listVSwitchesOptions = ListVSwitchesOptions.Builder.vpcId(vpcId).vSwitchId(vSwitchId);
+ return api.vSwitchApi().list(regionId, listVSwitchesOptions).first();
+ }
+
+ private String createSecurityGroupForOptions(String group, String regionId, String vpcId,
+ ECSServiceTemplateOptions options) {
+ String name = namingConvention.create().sharedNameForGroup(group);
+ SecurityGroupRequest securityGroupRequest = api.securityGroupApi().create(regionId,
+ CreateSecurityGroupOptions.Builder
+ .securityGroupName(name)
+ .vpcId(vpcId));
+ // add rules
+ Map<Integer, Integer> portRanges = getPortRangesFromList(options.getInboundPorts());
+ for (Map.Entry<Integer, Integer> portRange : portRanges.entrySet()) {
+ String range = String.format(PORT_RANGE_FORMAT, portRange.getKey(), portRange.getValue());
+ // TODO makes protocol and source CIDR configurable?
+ api.securityGroupApi().addInboundRule(
+ regionId,
+ securityGroupRequest.getSecurityGroupId(),
+ IpProtocol.TCP,
+ range,
+ INTERNET);
+ }
+ api.tagApi().add(regionId, securityGroupRequest.getSecurityGroupId(), SECURITYGROUP,
+ TagOptions.Builder
+ .tag(1, Tag.DEFAULT_OWNER_KEY, Tag.DEFAULT_OWNER_VALUE)
+ .tag(2, Tag.GROUP, group));
+ return securityGroupRequest.getSecurityGroupId();
+ }
+
+ private void registerAutoGeneratedKeyPairCleanupCallbacks(Map<?, ListenableFuture<Void>> responses,
+ final String regionId, final String keyPairName) {
+ // The Futures.allAsList fails immediately if some of the futures fail.
+ // The Futures.successfulAsList, however,
+ // returns a list containing the results or 'null' for those futures that
+ // failed. We want to wait for all them
+ // (even if they fail), so better use the latter form.
+ ListenableFuture<List<Void>> aggregatedResponses = Futures.successfulAsList(responses.values());
+
+ // Key pairs must be cleaned up after all futures completed (even if some
+ // failed).
+ Futures.addCallback(aggregatedResponses, new FutureCallback<List<Void>>() {
+ @Override
+ public void onSuccess(List<Void> result) {
+ cleanupAutoGeneratedKeyPairs(keyPairName);
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ cleanupAutoGeneratedKeyPairs(keyPairName);
+ }
+
+ private void cleanupAutoGeneratedKeyPairs(String keyPairName) {
+ logger.debug(">> cleaning up auto-generated key pairs...");
+ try {
+ api.sshKeyPairApi().delete(regionId, keyPairName);
+ } catch (Exception ex) {
+ logger.warn(">> could not delete key pair %s: %s", keyPairName, ex.getMessage());
+ }
+ }
+ }, userExecutor);
+ }
+
+
+ private static PublicKey readPublicKey(String publicKey) {
+ Iterable<String> parts = Splitter.on(' ').split(publicKey);
+ checkArgument(size(parts) >= 2, "bad format, should be: ssh-rsa AAAAB3...");
+ String type = get(parts, 0);
+
+ try {
+ if ("ssh-rsa".equals(type)) {
+ RSAPublicKeySpec spec = SshKeys.publicKeySpecFromOpenSSH(publicKey);
+ return KeyFactory.getInstance("RSA").generatePublic(spec);
+ } else {
+ throw new IllegalArgumentException("bad format, ssh-rsa is only supported");
+ }
+ } catch (InvalidKeySpecException ex) {
+ throw new RuntimeException(ex);
+ } catch (NoSuchAlgorithmException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+
+ private static String computeFingerprint(PublicKey key) {
+ if (key instanceof RSAPublicKey) {
+ RSAPublicKey rsaKey = (RSAPublicKey) key;
+ return SshKeys.fingerprint(rsaKey.getPublicExponent(), rsaKey.getModulus());
+ } else {
+ throw new IllegalArgumentException("Only RSA keys are supported");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/config/ECSComputeServiceHttpApiModule.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/config/ECSComputeServiceHttpApiModule.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/config/ECSComputeServiceHttpApiModule.java
index 05ebc9f..1e84c6b 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/config/ECSComputeServiceHttpApiModule.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/config/ECSComputeServiceHttpApiModule.java
@@ -16,15 +16,22 @@
*/
package org.jclouds.aliyun.ecs.config;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Provides;
import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
import org.jclouds.aliyun.ecs.handlers.ECSComputeServiceErrorHandler;
+import org.jclouds.aliyun.ecs.handlers.ECSErrorRetryHandler;
import org.jclouds.http.HttpErrorHandler;
+import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.rest.ConfiguresHttpApi;
import org.jclouds.rest.config.HttpApiModule;
+import javax.inject.Singleton;
+import java.util.Set;
+
@ConfiguresHttpApi
public class ECSComputeServiceHttpApiModule extends HttpApiModule<ECSComputeServiceApi> {
@@ -35,4 +42,21 @@ public class ECSComputeServiceHttpApiModule extends HttpApiModule<ECSComputeServ
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ECSComputeServiceErrorHandler.class);
}
+ @Override
+ protected void bindRetryHandlers() {
+ bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(ECSErrorRetryHandler.class);
+ }
+
+ /**
+ * It combines the error codes explicitly described as retryable from ECS and VPC
+ * https://error-center.alibabacloud.com/status/product/Ecs?spm=a2c63.p38356.a3.5.2a9859c1Fzi5nr
+ * https://error-center.alibabacloud.com/status/product/Vpc?spm=a2c63.p38356.a3.1.1442dd2f4qFMSW
+ */
+ @Provides
+ @ClientError
+ @Singleton
+ protected final Set<String> provideRetryableCodes() {
+ return ImmutableSet.of("InstanceNotReady", "IncorrectInstanceStatus.Initializing", "DependencyViolation", "IncorrectVpcStatus", "IncorrectStatus");
+ }
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AllocatePublicIpAddressRequest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AllocatePublicIpAddressRequest.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AllocatePublicIpAddressRequest.java
new file mode 100644
index 0000000..8f03160
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AllocatePublicIpAddressRequest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+import java.beans.ConstructorProperties;
+
+public class AllocatePublicIpAddressRequest extends Request {
+
+ private final String ipAddress;
+
+ @ConstructorProperties({ "RequestId", "IpAddress" })
+ public AllocatePublicIpAddressRequest(String requestId, String ipAddress) {
+ super(requestId);
+ this.ipAddress = ipAddress;
+ }
+
+ public String getInstanceId() {
+ return ipAddress;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ if (!super.equals(o))
+ return false;
+ AllocatePublicIpAddressRequest that = (AllocatePublicIpAddressRequest) o;
+ return Objects.equal(ipAddress, that.ipAddress);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), ipAddress);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("ipAddress", ipAddress).toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableResource.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableResource.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableResource.java
new file mode 100644
index 0000000..338663c
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableResource.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+import java.util.Map;
+
+@AutoValue
+public abstract class AvailableResource {
+
+ AvailableResource() {
+ }
+
+ @SerializedNames({ "Type", "SupportedResources" })
+ public static AvailableResource create(String type, Map<String, List<SupportedResource>> supportedResources) {
+ return new AutoValue_AvailableResource(type, supportedResources == null ?
+ ImmutableMap.<String, List<SupportedResource>>of() :
+ ImmutableMap.copyOf(supportedResources));
+ }
+
+ public abstract String type();
+
+ public abstract Map<String, List<SupportedResource>> supportedResources();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableZone.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableZone.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableZone.java
new file mode 100644
index 0000000..08e65b3
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/AvailableZone.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.json.SerializedNames;
+
+import java.util.List;
+import java.util.Map;
+
+@AutoValue
+public abstract class AvailableZone {
+
+ AvailableZone() {
+ }
+
+ @SerializedNames({ "Status", "RegionId", "AvailableResources", "ZoneId" })
+ public static AvailableZone create(String status, String regionId,
+ Map<String, List<AvailableResource>> availableResources, String zoneId) {
+ return new AutoValue_AvailableZone(status, regionId, availableResources == null ?
+ ImmutableMap.<String, List<AvailableResource>>of() :
+ ImmutableMap.copyOf(availableResources), zoneId);
+ }
+
+ public abstract String status();
+
+ public abstract String regionId();
+
+ public abstract Map<String, List<AvailableResource>> availableResources();
+
+ public abstract String zoneId();
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/DedicatedHostAttribute.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/DedicatedHostAttribute.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/DedicatedHostAttribute.java
new file mode 100644
index 0000000..dff8e3f
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/DedicatedHostAttribute.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class DedicatedHostAttribute {
+
+ DedicatedHostAttribute() {
+ }
+
+ @SerializedNames({ "DedicatedHostId", "DedicatedHostName" })
+ public static DedicatedHostAttribute create(String id, String name) {
+ return new AutoValue_DedicatedHostAttribute(id, name);
+ }
+
+ public abstract String id();
+
+ public abstract String name();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/EipAddress.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/EipAddress.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/EipAddress.java
new file mode 100644
index 0000000..10c158d
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/EipAddress.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Enums;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class EipAddress {
+
+ public enum InternetChargeType {
+ ECS_INSTANCE("EcsInstance"),
+ SLB_INSTANCE ("SlbInstance"),
+ NAT ("Nat"),
+ HA_VIP("HaVip"),
+ DEFAULT("");
+
+ private final String internetChargeType;
+
+ InternetChargeType(String internetChargeType) {
+ this.internetChargeType = internetChargeType;
+ }
+
+ public static InternetChargeType fromValue(String value) {
+ return Enums.getIfPresent(InternetChargeType.class, CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, value)).or(InternetChargeType.DEFAULT);
+ }
+
+ public String internetChargeType() {
+ return internetChargeType;
+ }
+
+ @Override
+ public String toString() {
+ return internetChargeType();
+ }
+ }
+
+ EipAddress() {}
+
+ @SerializedNames({ "IpAddress", "AllocationId", "InternetChargeType" })
+ public static EipAddress create(String ipAddress, String allocationId, InternetChargeType internetChargeType) {
+ return new AutoValue_EipAddress(ipAddress, allocationId, internetChargeType);
+ }
+
+ public abstract String ipAddress();
+
+ public abstract String allocationId();
+
+ public abstract InternetChargeType internetChargeType();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ErrorMessage.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ErrorMessage.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ErrorMessage.java
new file mode 100644
index 0000000..aa3f684
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ErrorMessage.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class ErrorMessage {
+
+ ErrorMessage() {}
+
+ @SerializedNames({ "RequestId", "HostId", "Code", "Message" })
+ public static ErrorMessage create(String requestId, String hostId, String code, String message) {
+ return new AutoValue_ErrorMessage(requestId, hostId, code, message);
+ }
+
+ public abstract String requestId();
+
+ public abstract String hostId();
+
+ public abstract String code();
+
+ public abstract String message();
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Image.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Image.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Image.java
index 328d6fe..1aee2c1 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Image.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Image.java
@@ -17,6 +17,10 @@
package org.jclouds.aliyun.ecs.domain;
import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
import com.google.common.collect.ImmutableMap;
import org.jclouds.json.SerializedNames;
@@ -24,9 +28,31 @@ import java.util.Date;
import java.util.List;
import java.util.Map;
+import static com.google.common.base.Preconditions.checkArgument;
+
@AutoValue
public abstract class Image {
+ public enum Status {
+ AVAILABLE, UNAVAILABLE;
+
+
+ public static Status fromValue(String value) {
+ Optional<Status> status = Enums.getIfPresent(Status.class, value.toUpperCase());
+ checkArgument(status.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(Status.values()), value);
+ return status.get();
+ }
+
+ public String value() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+ }
+
+ @Override
+ public String toString() {
+ return value();
+ }
+ }
+
Image() {}
@SerializedNames({"ImageId", "Description", "ProductCode", "OSType", "Architecture", "OSName", "DiskDeviceMappings",
@@ -36,15 +62,15 @@ public abstract class Image {
public static Image create(String id, String description, String productCode, String osType,
String architecture, String osName, Map<String, List<DiskDeviceMapping>> diskDeviceMappings,
String imageOwnerAlias, String progress, Boolean isSupportCloudinit, String usage, Date creationTime,
- Map<String, List<Tag>> tags, String imageVersion, String status, String name,
+ Map<String, List<Tag>> tags, String imageVersion, Status status, String name,
Boolean isSupportIoOptimized, Boolean isSelfShared, Boolean isCopied, Boolean isSubscribed, String platform,
- String size) {
- return new AutoValue_Image(id, description, productCode, osType, architecture, osName,
- diskDeviceMappings == null ?
- ImmutableMap.<String, List<DiskDeviceMapping>>of() :
- ImmutableMap.copyOf(diskDeviceMappings), imageOwnerAlias, progress, isSupportCloudinit, usage,
- creationTime, tags == null ? ImmutableMap.<String, List<Tag>>of() : ImmutableMap.copyOf(tags), imageVersion,
- status, name, isSupportIoOptimized, isSelfShared, isCopied, isSubscribed, platform, size);
+ int size) {
+ return builder().id(id).description(description).productCode(productCode).osType(osType)
+ .architecture(architecture).osName(osName).diskDeviceMappings(diskDeviceMappings).imageOwnerAlias(imageOwnerAlias)
+ .progress(progress).isSupportCloudinit(isSupportCloudinit).usage(usage).creationTime(creationTime)
+ .tags(tags).imageVersion(imageVersion).status(status).name(name).isSupportIoOptimizeds(isSupportIoOptimized)
+ .isSelfShared(isSelfShared).isCopied(isCopied).isSubscribed(isSubscribed).platform(platform).size(size)
+ .build();
}
public abstract String id();
@@ -75,7 +101,7 @@ public abstract class Image {
public abstract String imageVersion();
- public abstract String status();
+ public abstract Status status();
public abstract String name();
@@ -89,6 +115,72 @@ public abstract class Image {
public abstract String platform();
- public abstract String size();
+ public abstract int size();
+
+ public abstract Builder toBuilder();
+
+ public static Builder builder() {
+ return new AutoValue_Image.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder id(String id);
+
+ public abstract Builder description(String description);
+
+ public abstract Builder productCode(String productCode);
+
+ public abstract Builder osType(String osType);
+
+ public abstract Builder architecture(String architecture);
+
+ public abstract Builder osName(String osName);
+
+ public abstract Builder diskDeviceMappings(Map<String, List<DiskDeviceMapping>> diskDeviceMappings);
+
+ public abstract Builder imageOwnerAlias(String imageOwnerAlias);
+
+ public abstract Builder progress(String progress);
+
+ public abstract Builder isSupportCloudinit(Boolean isSupportCloudinit);
+
+ public abstract Builder usage(String usage);
+
+ public abstract Builder creationTime(Date creationTime);
+
+ public abstract Builder tags(Map<String, List<Tag>> tags);
+
+ public abstract Builder imageVersion(String imageVersion);
+
+ public abstract Builder status(Status status);
+
+ public abstract Builder name(String name);
+
+ public abstract Builder isSupportIoOptimizeds(Boolean isSupportIoOptimizeds);
+
+ public abstract Builder isSelfShared(Boolean isSelfShared);
+
+ public abstract Builder isCopied(Boolean isCopied);
+
+ public abstract Builder isSubscribed(Boolean isSubscribed);
+
+ public abstract Builder platform(String platform);
+
+ public abstract Builder size(int size);
+
+ abstract Image autoBuild();
+
+ abstract Map<String, List<DiskDeviceMapping>> diskDeviceMappings();
+
+ abstract Map<String, List<Tag>> tags();
+
+ public Image build() {
+ diskDeviceMappings(diskDeviceMappings() != null ? ImmutableMap.copyOf(diskDeviceMappings()) : ImmutableMap.<String, List<DiskDeviceMapping>>of());
+ tags(tags() != null ? ImmutableMap.copyOf(tags()) : ImmutableMap.<String, List<Tag>>of());
+ return autoBuild();
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Instance.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Instance.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Instance.java
new file mode 100644
index 0000000..ddf2036
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Instance.java
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+@AutoValue
+public abstract class Instance {
+
+ public enum InternetChargeType {
+ PAY_BY_TRAFFIC("PayByTraffic"),
+ DEFAULT("");
+
+ private final String internetChargeType;
+
+ InternetChargeType(String internetChargeType) {
+ this.internetChargeType = internetChargeType;
+ }
+
+ public static InternetChargeType fromValue(String value) {
+ return Enums.getIfPresent(InternetChargeType.class, CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, value)).or(InternetChargeType.DEFAULT);
+ }
+
+ public String internetChargeType() {
+ return internetChargeType;
+ }
+
+ @Override
+ public String toString() {
+ return internetChargeType();
+ }
+ }
+
+
+ public enum Status {
+ STARTING, RUNNING, STOPPING, STOPPED;
+
+ public static Status fromValue(String value) {
+ Optional<Status> status = Enums.getIfPresent(Status.class, value.toUpperCase());
+ checkArgument(status.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(Status.values()),
+ value);
+ return status.get();
+ }
+ }
+
+ Instance() {}
+
+ @SerializedNames(
+ { "InnerIpAddress", "ImageId", "InstanceTypeFamily", "VlanId", "NetworkInterfaces", "InstanceId", "EipAddress",
+ "InternetMaxBandwidthIn", "ZoneId", "InternetChargeType", "SpotStrategy", "StoppedMode", "SerialNumber",
+ "IoOptimized", "Memory", "Cpu", "VpcAttributes", "InternetMaxBandwidthOut", "DeviceAvailable",
+ "SecurityGroupIds", "SaleCycle", "SpotPriceLimit", "AutoReleaseTime", "StartTime", "InstanceName",
+ "Description", "ResourceGroupId", "OSType", "OSName", "InstanceNetworkType", "PublicIpAddress",
+ "HostName", "InstanceType", "CreationTime", "Status", "Tags", "ClusterId", "Recyclable", "RegionId",
+ "GPUSpec", "DedicatedHostAttribute", "OperationLocks", "InstanceChargeType", "GPUAmount",
+ "ExpiredTime" })
+ public static Instance create(Map<String, List<String>> innerIpAddress, String imageId, String instanceTypeFamily,
+ String vlanId, Map<String, List<NetworkInterface>> networkInterfaces, String id, EipAddress eipAddress,
+ Integer internetMaxBandwidthIn, String zoneId, InternetChargeType internetChargeType, String spotStrategy,
+ String stoppedMode, String serialNumber, Boolean ioOptimized, Integer memory, Integer cpu,
+ VpcAttributes vpcAttributes, Integer internetMaxBandwidthOut, Boolean deviceAvailable,
+ Map<String, List<String>> securityGroupIds, String saleCycle, Double spotPriceLimit, String autoReleaseTime,
+ Date startTime, String name, String description, String resourceGroupId, String osType, String osName,
+ String instanceNetworkType, Map<String, List<String>> publicIpAddress, String hostname, String instanceType,
+ Date creationTime, Status status, Map<String, List<Tag>> tags, String clusterId, Boolean recyclable,
+ String regionId, String gpuSpec, DedicatedHostAttribute dedicatedHostAttribute,
+ Map<String, List<String>> operationLocks, String instanceChargeType, Integer gpuAmount, Date expiredTime) {
+ return builder().innerIpAddress(innerIpAddress).imageId(imageId).instanceTypeFamily(instanceTypeFamily).vlanId(vlanId)
+ .networkInterfaces(networkInterfaces).id(id).eipAddress(eipAddress).internetMaxBandwidthIn(internetMaxBandwidthIn)
+ .zoneId(zoneId).internetChargeType(internetChargeType).spotStrategy(spotStrategy).stoppedMode(stoppedMode).serialNumber(serialNumber)
+ .ioOptimized(ioOptimized).memory(memory).cpu(cpu).vpcAttributes(vpcAttributes).internetMaxBandwidthOut(internetMaxBandwidthOut).deviceAvailable(deviceAvailable)
+ .securityGroupIds(securityGroupIds).saleCycle(saleCycle).spotPriceLimit(spotPriceLimit).autoReleaseTime(autoReleaseTime).startTime(startTime).name(name)
+ .description(description).resourceGroupId(resourceGroupId).osType(osType).osName(osName).instanceNetworkType(instanceNetworkType).publicIpAddress(publicIpAddress)
+ .hostname(hostname).instanceType(instanceType).creationTime(creationTime).status(status).tags(tags).clusterId(clusterId).recyclable(recyclable).regionId(regionId)
+ .gpuSpec(gpuSpec).dedicatedHostAttribute(dedicatedHostAttribute).operationLocks(operationLocks).instanceChargeType(instanceChargeType).gpuAmount(gpuAmount)
+ .expiredTime(expiredTime).build();
+ }
+
+ public abstract Map<String, List<String>> innerIpAddress();
+
+ public abstract String imageId();
+
+ public abstract String instanceTypeFamily();
+
+ public abstract String vlanId();
+
+ public abstract Map<String, List<NetworkInterface>> networkInterfaces();
+
+ public abstract String id();
+
+ public abstract EipAddress eipAddress();
+
+ public abstract Integer internetMaxBandwidthIn();
+
+ public abstract String zoneId();
+
+ public abstract InternetChargeType internetChargeType();
+
+ public abstract String spotStrategy();
+
+ public abstract String stoppedMode();
+
+ public abstract String serialNumber();
+
+ public abstract Boolean ioOptimized();
+
+ public abstract Integer memory();
+
+ public abstract Integer cpu();
+
+ public abstract VpcAttributes vpcAttributes();
+
+ public abstract Integer internetMaxBandwidthOut();
+
+ public abstract Boolean deviceAvailable();
+
+ public abstract Map<String, List<String>> securityGroupIds();
+
+ public abstract String saleCycle();
+
+ public abstract Double spotPriceLimit();
+
+ public abstract String autoReleaseTime();
+
+ public abstract Date startTime();
+
+ public abstract String name();
+
+ public abstract String description();
+
+ public abstract String resourceGroupId();
+
+ public abstract String osType();
+
+ public abstract String osName();
+
+ public abstract String instanceNetworkType();
+
+ public abstract Map<String, List<String>> publicIpAddress();
+
+ public abstract String hostname();
+
+ public abstract String instanceType();
+
+ public abstract Date creationTime();
+
+ public abstract Status status();
+
+ @Nullable
+ public abstract Map<String, List<Tag>> tags();
+
+ public abstract String clusterId();
+
+ public abstract Boolean recyclable();
+
+ public abstract String regionId();
+
+ public abstract String gpuSpec();
+
+ public abstract DedicatedHostAttribute dedicatedHostAttribute();
+
+ public abstract Map<String, List<String>> operationLocks();
+
+ public abstract String instanceChargeType();
+
+ public abstract Integer gpuAmount();
+
+ public abstract Date expiredTime();
+
+ public abstract Builder toBuilder();
+
+ public static Builder builder() {
+ return new AutoValue_Instance.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder innerIpAddress(Map<String, List<String>> innerIpAddress);
+
+ public abstract Builder imageId(String imageId);
+
+ public abstract Builder instanceTypeFamily(String instanceTypeFamily);
+
+ public abstract Builder vlanId(String vlanId);
+
+ public abstract Builder networkInterfaces(Map<String, List<NetworkInterface>> networkInterfaces);
+
+ public abstract Builder id(String id);
+
+ public abstract Builder eipAddress(EipAddress eipAddress);
+
+ public abstract Builder internetMaxBandwidthIn(Integer internetMaxBandwidthIn);
+
+ public abstract Builder zoneId(String zoneId);
+
+ public abstract Builder internetChargeType(InternetChargeType internetChargeType);
+
+ public abstract Builder spotStrategy(String spotStrategy);
+
+ public abstract Builder stoppedMode(String stoppedMode);
+
+ public abstract Builder serialNumber(String serialNumber);
+
+ public abstract Builder ioOptimized(Boolean ioOptimized);
+
+ public abstract Builder memory(Integer memory);
+
+ public abstract Builder cpu(Integer cpu);
+
+ public abstract Builder vpcAttributes(VpcAttributes vpcAttributes);
+
+ public abstract Builder internetMaxBandwidthOut(Integer internetMaxBandwidthOut);
+
+ public abstract Builder deviceAvailable(Boolean deviceAvailable);
+
+ public abstract Builder securityGroupIds(Map<String, List<String>> securityGroupIds);
+
+ public abstract Builder saleCycle(String saleCycle);
+
+ public abstract Builder spotPriceLimit(Double spotPriceLimit);
+
+ public abstract Builder autoReleaseTime(String autoReleaseTime);
+
+ public abstract Builder startTime(Date startTime);
+
+ public abstract Builder name(String name);
+
+ public abstract Builder description(String description);
+
+ public abstract Builder resourceGroupId(String resourceGroupId);
+
+ public abstract Builder osType(String osType);
+
+ public abstract Builder osName(String osName);
+
+ public abstract Builder instanceNetworkType(String instanceNetworkType);
+
+ public abstract Builder publicIpAddress(Map<String, List<String>> publicIpAddress);
+
+ public abstract Builder hostname(String hostname);
+
+ public abstract Builder instanceType(String instanceType);
+
+ public abstract Builder creationTime(Date creationTime);
+
+ public abstract Builder status(Status status);
+
+ public abstract Builder tags(Map<String, List<Tag>> tags);
+
+ public abstract Builder clusterId(String clusterId);
+
+ public abstract Builder recyclable(Boolean recyclable);
+
+ public abstract Builder regionId(String regionId);
+
+ public abstract Builder gpuSpec(String gpuSpec);
+
+ public abstract Builder dedicatedHostAttribute(DedicatedHostAttribute dedicatedHostAttribute);
+
+ public abstract Builder operationLocks(Map<String, List<String>> operationLocks);
+
+ public abstract Builder instanceChargeType(String InstanceChargeType);
+
+ public abstract Builder gpuAmount(Integer gpuAmount);
+
+ public abstract Builder expiredTime(Date expiredTime);
+
+ abstract Instance autoBuild();
+
+ abstract Map<String, List<String>> innerIpAddress();
+
+ abstract Map<String, List<NetworkInterface>> networkInterfaces();
+
+ abstract Map<String, List<String>> securityGroupIds();
+
+ abstract Map<String, List<String>> publicIpAddress();
+
+ abstract Map<String, List<String>> operationLocks();
+
+ abstract Map<String, List<Tag>> tags();
+
+ public Instance build() {
+ innerIpAddress(innerIpAddress() == null ? ImmutableMap.<String, List<String>>of() : ImmutableMap.copyOf(innerIpAddress()));
+ securityGroupIds(securityGroupIds() == null ? ImmutableMap.<String, List<String>>of() : ImmutableMap.copyOf(securityGroupIds()));
+ networkInterfaces(networkInterfaces() == null ? ImmutableMap.<String, List<NetworkInterface>>of() : ImmutableMap.copyOf(networkInterfaces()));
+ publicIpAddress(publicIpAddress() == null ? ImmutableMap.<String, List<String>>of() : ImmutableMap.copyOf(publicIpAddress()));
+ operationLocks(operationLocks() == null ? ImmutableMap.<String, List<String>>of() : ImmutableMap.copyOf(operationLocks()));
+ tags(tags() != null ? ImmutableMap.copyOf(tags()) : ImmutableMap.<String, List<Tag>>of());
+ return autoBuild();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceRequest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceRequest.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceRequest.java
new file mode 100644
index 0000000..ca615d0
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceRequest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+import java.beans.ConstructorProperties;
+
+public class InstanceRequest extends Request {
+
+ private final String instanceId;
+
+ @ConstructorProperties({ "RequestId", "InstanceId" })
+ public InstanceRequest(String requestId, String instanceId) {
+ super(requestId);
+ this.instanceId = instanceId;
+ }
+
+ public String getInstanceId() {
+ return instanceId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ if (!super.equals(o))
+ return false;
+ InstanceRequest that = (InstanceRequest) o;
+ return Objects.equal(instanceId, that.instanceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), instanceId);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("instanceId", instanceId).toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceStatus.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceStatus.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceStatus.java
new file mode 100644
index 0000000..4ee6777
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceStatus.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import org.jclouds.json.SerializedNames;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * https://www.alibabacloud.com/help/doc-detail/25687.htm?spm=a2c63.p38356.a3.3.25a15566k0U5A4
+ */
+@AutoValue
+public abstract class InstanceStatus {
+
+ InstanceStatus() {
+ }
+
+ @SerializedNames({ "InstanceId", "Status" })
+ public static InstanceStatus create(String instanceId, Status status) {
+ return new AutoValue_InstanceStatus(instanceId, status);
+ }
+
+ public abstract String instanceId();
+
+ public abstract Status status();
+
+ public enum Status {
+ PENDING, STARTING, RUNNING, STOPPING, STOPPED;
+
+ public static InstanceStatus.Status fromValue(String value) {
+ Optional<Status> status = Enums.getIfPresent(InstanceStatus.Status.class, value.toUpperCase());
+ checkArgument(status.isPresent(), "Expected one of %s but was %s",
+ Joiner.on(',').join(InstanceStatus.Status.values()), value);
+ return status.get();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceType.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceType.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceType.java
new file mode 100644
index 0000000..1802084
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/InstanceType.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class InstanceType {
+
+ InstanceType() {
+ }
+
+ @SerializedNames(
+ {"InstanceTypeId", "InstanceTypeFamily", "EniQuantity",
+ "GPUSpec", "CpuCoreCount", "MemorySize", "GPUAmount", "LocalStorageCategory" })
+ public static InstanceType create(String id, String instanceTypeFamily, Integer eniQuantity,
+ String gpuSpec, Integer cpuCoreCount, Double memorySize, Double gpuAmount, String localStorageCategory) {
+ return builder()
+ .id(id).instanceTypeFamily(instanceTypeFamily).eniQuantity(eniQuantity)
+ .gpuSpec(gpuSpec).cpuCoreCount(cpuCoreCount).memorySize(memorySize)
+ .gpuAmount(gpuAmount).localStorageCategory(localStorageCategory)
+ .build();
+ }
+
+ public abstract String id();
+
+ public abstract Integer cpuCoreCount();
+
+ public abstract String instanceTypeFamily();
+
+ public abstract Integer eniQuantity();
+
+ public abstract String gpuSpec();
+
+ public abstract Double memorySize();
+
+ public abstract Double gpuAmount();
+
+ public abstract String localStorageCategory();
+
+ public abstract Builder toBuilder();
+
+ public static Builder builder() {
+ return new AutoValue_InstanceType.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder id(String id);
+
+ public abstract Builder cpuCoreCount(Integer cpuCoreCount);
+
+ public abstract Builder instanceTypeFamily(String instanceTypeFamily);
+
+ public abstract Builder eniQuantity(Integer eniQuantity);
+
+ public abstract Builder gpuSpec(String gpuSpec);
+
+ public abstract Builder memorySize(Double memorySize);
+
+ public abstract Builder gpuAmount(Double gpuAmount);
+
+ public abstract Builder localStorageCategory(String localStorageCategory);
+
+ public abstract InstanceType build();
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/NetworkInterface.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/NetworkInterface.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/NetworkInterface.java
new file mode 100644
index 0000000..6a3b6e9
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/NetworkInterface.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+@AutoValue
+public abstract class NetworkInterface {
+
+ NetworkInterface() {
+ }
+
+ @SerializedNames({ "MacAddress", "PrimaryIpAddress", "NetworkInterfaceId" })
+ public static NetworkInterface create(String macAddress, String primaryIpAddress, String id) {
+ return new AutoValue_NetworkInterface(macAddress, primaryIpAddress, id);
+ }
+
+ @Nullable
+ public abstract String macAddress();
+
+ public abstract String primaryIpAddress();
+
+ public abstract String id();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Permission.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Permission.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Permission.java
index 003ccf1..bda9cb5 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Permission.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Permission.java
@@ -50,7 +50,7 @@ public abstract class Permission {
}
public enum Direction {
- EGRESS, ALL;
+ EGRESS, INGRESS, ALL;
public static Direction fromValue(String value) {
Optional<Direction> direction = Enums.getIfPresent(Direction.class, value.toUpperCase());
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ResourceType.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ResourceType.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ResourceType.java
new file mode 100644
index 0000000..9807d83
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/ResourceType.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * The type of the ECS resource. All values must be lowercase.
+ */
+public enum ResourceType {
+ DISK, INSTANCE, IMAGE, SECURITYGROUP, SNAPSHOT;
+
+ public static ResourceType fromValue(String value) {
+ Optional<ResourceType> resourceType = Enums.getIfPresent(ResourceType.class, value.toUpperCase());
+ checkArgument(resourceType.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(ResourceType.values()), value);
+ return resourceType.get();
+ }
+
+ @Override
+ public String toString() {
+ return name().toLowerCase();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SecurityGroup.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SecurityGroup.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SecurityGroup.java
index 3fd0658..8709948 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SecurityGroup.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SecurityGroup.java
@@ -17,18 +17,24 @@
package org.jclouds.aliyun.ecs.domain;
import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableMap;
import org.jclouds.json.SerializedNames;
+import java.util.List;
+import java.util.Map;
+
@AutoValue
public abstract class SecurityGroup {
SecurityGroup() {
}
- @SerializedNames({ "SecurityGroupId", "Description", "SecurityGroupName", "VpcId" })
+ @SerializedNames({ "SecurityGroupId", "Description", "SecurityGroupName", "VpcId", "Tags" })
public static SecurityGroup create(String id, String description, String name,
- String vpcId) {
- return new AutoValue_SecurityGroup(id, description, name, vpcId);
+ String vpcId, Map<String, List<Tag>> tags) {
+ return new AutoValue_SecurityGroup(id, description, name, vpcId, tags == null ?
+ ImmutableMap.<String, List<Tag>>of() :
+ ImmutableMap.copyOf(tags));
}
public abstract String id();
@@ -39,4 +45,6 @@ public abstract class SecurityGroup {
public abstract String vpcId();
+ public abstract Map<String, List<Tag>> tags();
+
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SupportedResource.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SupportedResource.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SupportedResource.java
new file mode 100644
index 0000000..3547004
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/SupportedResource.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import org.jclouds.json.SerializedNames;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+@AutoValue
+public abstract class SupportedResource {
+
+ public enum Status {
+ AVAILABLE, SOLDOUT;
+
+ public static Status fromValue(String value) {
+ Optional<Status> status = Enums.getIfPresent(Status.class, value.toUpperCase());
+ checkArgument(status.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(Status.values()), value);
+ return status.get();
+ }
+ }
+
+ SupportedResource() {
+ }
+
+ @SerializedNames({ "Status", "Value" })
+ public static SupportedResource create(Status status, String value) {
+ return new AutoValue_SupportedResource(status, value);
+ }
+
+ public abstract Status status();
+
+ public abstract String value();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Tag.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Tag.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Tag.java
index 1b34226..33bc688 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Tag.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/Tag.java
@@ -17,19 +17,25 @@
package org.jclouds.aliyun.ecs.domain;
import com.google.auto.value.AutoValue;
+import org.jclouds.javax.annotation.Nullable;
import org.jclouds.json.SerializedNames;
@AutoValue
public abstract class Tag {
+ public static final String DEFAULT_OWNER_KEY = "owner";
+ public static final String DEFAULT_OWNER_VALUE = "jclouds";
+ public static final String GROUP = "group";
+
Tag() {}
@SerializedNames({ "TagKey", "TagValue" })
- public static Tag create(String tagKey, String tagValue) {
- return new AutoValue_Tag(tagKey, tagValue);
+ public static Tag create(String key, String value) {
+ return new AutoValue_Tag(key, value);
}
- public abstract String tagKey();
+ public abstract String key();
- public abstract String tagValue();
+ @Nullable
+ public abstract String value();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/UserCidr.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/UserCidr.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/UserCidr.java
new file mode 100644
index 0000000..ff91eae
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/UserCidr.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+
+// FIXME not possible to find properties from either the API or the doc
+@AutoValue
+public abstract class UserCidr {
+
+ UserCidr() {}
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPC.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPC.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPC.java
new file mode 100644
index 0000000..a1ed1d6
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPC.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+@AutoValue
+public abstract class VPC {
+
+ public enum Status {
+ AVAILABLE, UNAVAILABLE, PENDING;
+
+ public static Status fromValue(String value) {
+ Optional<Status> status = Enums.getIfPresent(Status.class, value.toUpperCase());
+ checkArgument(status.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(Status.values()), value);
+ return status.get();
+ }
+
+ public String value() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+ }
+
+ @Override
+ public String toString() {
+ return value();
+ }
+ }
+
+ VPC() {}
+
+ @SerializedNames({"CidrBlock", "CreationTime", "Description", "RegionId", "Status",
+ "UserCidrs", "VRouterId", "VSwitchIds", "VpcId", "VpcName" })
+ public static VPC create(String cidrBlock, Date creationTime, String description, String regionId, Status status,
+ Map<String, List<UserCidr>> userCidrs,
+ String vRouterId,
+ Map<String, List<String>> vSwitchIds,
+ String id, String name) {
+ return builder().cidrBlock(cidrBlock).creationTime(creationTime).description(description).regionId(regionId)
+ .status(status).userCidrs(userCidrs).vRouterId(vRouterId).vSwitchIds(vSwitchIds)
+ .id(id).name(name).build();
+ }
+
+ public abstract String cidrBlock();
+
+ public abstract Date creationTime();
+
+ public abstract String description();
+
+ public abstract String regionId();
+
+ public abstract Status status();
+
+ public abstract Map<String, List<UserCidr>> userCidrs();
+
+ public abstract String vRouterId();
+
+ public abstract Map<String, List<String>> vSwitchIds();
+
+ public abstract String id();
+
+ public abstract String name();
+
+ public abstract VPC.Builder toBuilder();
+
+ public static VPC.Builder builder() {
+ return new AutoValue_VPC.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder cidrBlock(String cidrBlock);
+
+ public abstract Builder creationTime(Date creationTime);
+
+ public abstract Builder description(String description);
+
+ public abstract Builder regionId(String regionId);
+
+ public abstract Builder status(Status status);
+
+ public abstract Builder userCidrs(Map<String, List<UserCidr>> userCidrs);
+
+ public abstract Builder vRouterId(String vRouterId);
+
+ public abstract Builder vSwitchIds(Map<String, List<String>> vSwitchIds);
+
+ public abstract Builder id(String id);
+
+ public abstract Builder name(String name);
+
+ abstract VPC autoBuild();
+
+ abstract Map<String, List<UserCidr>> userCidrs();
+
+ abstract Map<String, List<String>> vSwitchIds();
+
+ public VPC build() {
+ userCidrs(userCidrs() == null ? ImmutableMap.<String, List<UserCidr>>of() : ImmutableMap.copyOf(userCidrs()));
+ vSwitchIds(vSwitchIds() == null ? ImmutableMap.<String, List<String>>of() : ImmutableMap.copyOf(vSwitchIds()));
+ return autoBuild();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPCRequest.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPCRequest.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPCRequest.java
new file mode 100644
index 0000000..868c550
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VPCRequest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+import java.beans.ConstructorProperties;
+
+public class VPCRequest extends Request {
+
+ private final String routeTableId;
+ private final String vRouterId;
+ private final String vpcId;
+
+ @ConstructorProperties({ "RequestId", "RouteTableId", "VRouterId", "VpcId" })
+ public VPCRequest(String requestId, String routeTableId, String vRouterId, String vpcId) {
+ super(requestId);
+ this.routeTableId = routeTableId;
+ this.vRouterId = vRouterId;
+ this.vpcId = vpcId;
+ }
+
+ public String getRouteTableId() {
+ return routeTableId;
+ }
+
+ public String getvRouterId() {
+ return vRouterId;
+ }
+
+ public String getVpcId() {
+ return vpcId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+ VPCRequest that = (VPCRequest) o;
+ return Objects.equal(routeTableId, that.routeTableId) &&
+ Objects.equal(vRouterId, that.vRouterId) &&
+ Objects.equal(vpcId, that.vpcId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), routeTableId, vRouterId, vpcId);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("routeTableId", routeTableId)
+ .add("vRouterId", vRouterId)
+ .add("vpcId", vpcId)
+ .toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitch.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitch.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitch.java
new file mode 100644
index 0000000..9f73e30
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/domain/VSwitch.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.domain;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Enums;
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import org.jclouds.json.SerializedNames;
+
+import java.util.Date;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+@AutoValue
+public abstract class VSwitch {
+
+ public enum Status {
+ AVAILABLE, UNAVAILABLE, PENDING;
+
+ public static Status fromValue(String value) {
+ Optional<Status> status = Enums.getIfPresent(Status.class, value.toUpperCase());
+ checkArgument(status.isPresent(), "Expected one of %s but was %s", Joiner.on(',').join(Status.values()), value);
+ return status.get();
+ }
+
+ public String value() {
+ return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, name());
+ }
+
+ @Override
+ public String toString() {
+ return value();
+ }
+ }
+
+ VSwitch() {}
+
+ @SerializedNames({"CidrBlock", "CreationTime", "Description", "ZoneId", "Status",
+ "AvailableIpAddressCount", "VpcId", "VSwitchId", "VSwitchName" })
+ public static VSwitch create(String cidrBlock, Date creationTime, String description, String zoneId, Status status,
+ int availableIpAddressCount,
+ String vpcId, String id, String name) {
+ return builder().cidrBlock(cidrBlock).creationTime(creationTime).description(description).zoneId(zoneId).status(status)
+ .availableIpAddressCount(availableIpAddressCount).vpcId(vpcId).id(id).name(name).build();
+ }
+
+ public abstract String cidrBlock();
+
+ public abstract Date creationTime();
+
+ public abstract String description();
+
+ public abstract String zoneId();
+
+ public abstract Status status();
+
+ public abstract int availableIpAddressCount();
+
+ public abstract String vpcId();
+
+ public abstract String id();
+
+ public abstract String name();
+
+ public abstract Builder toBuilder();
+
+ public static Builder builder() {
+ return new AutoValue_VSwitch.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder cidrBlock(String cidrBlock);
+
+ public abstract Builder creationTime(Date creationTime);
+
+ public abstract Builder description(String description);
+
+ public abstract Builder zoneId(String regionId);
+
+ public abstract Builder status(Status status);
+
+ public abstract Builder availableIpAddressCount(int availableIpAddressCount);
+
+ public abstract Builder vpcId(String vpcId);
+
+ public abstract Builder id(String id);
+
+ public abstract Builder name(String name);
+
+ abstract VSwitch build();
+ }
+
+
+}
[7/7] jclouds-labs git commit: [JCLOUDS-1430] Aliyun ECS
Posted by an...@apache.org.
[JCLOUDS-1430] Aliyun ECS
- add instance API
- add compute abstraction
- add validation for vpc and vSwitch IDs
- add builders for Image and Instance
- add unit tests for compute/functions
- add pagination to instanceStatus api
- rename provider id
- clean up code
- add network apis
- vpc api + tests
- vswitch api + tests
- improve CreateResourcesThenCreateNodes
- create default vpc and vswitch in case needed
- fix InstanceApiLiveTest
- add ECSDependencyViolationRetryHandler
- add ErrorRetryHandler
- fix ListImagesOptions.imageId
- fix enums in Instance and EIPAddress
Project: http://git-wip-us.apache.org/repos/asf/jclouds-labs/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds-labs/commit/2c7db7e8
Tree: http://git-wip-us.apache.org/repos/asf/jclouds-labs/tree/2c7db7e8
Diff: http://git-wip-us.apache.org/repos/asf/jclouds-labs/diff/2c7db7e8
Branch: refs/heads/master
Commit: 2c7db7e809085a7738d76f5714663231dff0a9f3
Parents: a5dbf00
Author: andreaturli <an...@gmail.com>
Authored: Tue Jul 3 14:47:43 2018 +0200
Committer: Andrea Turli <an...@gmail.com>
Committed: Tue Sep 11 21:19:59 2018 -0700
----------------------------------------------------------------------
aliyun-ecs/README.md | 43 +
aliyun-ecs/pom.xml | 3 -
.../aliyun/ecs/ECSComputeServiceApi.java | 11 +
.../ecs/ECSComputeServiceProviderMetadata.java | 4 +-
.../aliyun/ecs/ECSServiceApiMetadata.java | 6 +-
.../aliyun/ecs/compute/ECSComputeService.java | 154 +
.../ecs/compute/ECSComputeServiceAdapter.java | 278 ++
.../compute/config/ECSServiceContextModule.java | 160 +
.../compute/functions/ImageInRegionToImage.java | 104 +
.../functions/InstanceStatusToStatus.java | 44 +
.../functions/InstanceToNodeMetadata.java | 126 +
.../functions/InstanceTypeToHardware.java | 49 +
.../ecs/compute/functions/RegionToLocation.java | 54 +
.../functions/internal/OperatingSystems.java | 51 +
.../options/ECSServiceTemplateOptions.java | 180 +
.../ecs/compute/strategy/CleanupResources.java | 112 +
.../CreateResourcesThenCreateNodes.java | 360 ++
.../config/ECSComputeServiceHttpApiModule.java | 24 +
.../domain/AllocatePublicIpAddressRequest.java | 59 +
.../aliyun/ecs/domain/AvailableResource.java | 43 +
.../aliyun/ecs/domain/AvailableZone.java | 47 +
.../ecs/domain/DedicatedHostAttribute.java | 37 +
.../jclouds/aliyun/ecs/domain/EipAddress.java | 67 +
.../jclouds/aliyun/ecs/domain/ErrorMessage.java | 39 +
.../org/jclouds/aliyun/ecs/domain/Image.java | 112 +-
.../org/jclouds/aliyun/ecs/domain/Instance.java | 321 ++
.../aliyun/ecs/domain/InstanceRequest.java | 59 +
.../aliyun/ecs/domain/InstanceStatus.java | 55 +
.../jclouds/aliyun/ecs/domain/InstanceType.java | 85 +
.../aliyun/ecs/domain/NetworkInterface.java | 41 +
.../jclouds/aliyun/ecs/domain/Permission.java | 2 +-
.../jclouds/aliyun/ecs/domain/ResourceType.java | 42 +
.../aliyun/ecs/domain/SecurityGroup.java | 14 +-
.../aliyun/ecs/domain/SupportedResource.java | 52 +
.../java/org/jclouds/aliyun/ecs/domain/Tag.java | 14 +-
.../org/jclouds/aliyun/ecs/domain/UserCidr.java | 27 +
.../java/org/jclouds/aliyun/ecs/domain/VPC.java | 131 +
.../jclouds/aliyun/ecs/domain/VPCRequest.java | 74 +
.../org/jclouds/aliyun/ecs/domain/VSwitch.java | 112 +
.../aliyun/ecs/domain/VSwitchRequest.java | 58 +
.../aliyun/ecs/domain/VpcAttributes.java | 48 +
.../domain/internal/PaginatedCollection.java | 4 +-
.../domain/options/CreateInstanceOptions.java | 161 +
.../ecs/domain/options/CreateVPCOptions.java | 106 +
.../domain/options/CreateVSwitchOptions.java | 74 +
.../ecs/domain/options/ListImagesOptions.java | 6 +-
.../options/ListInstanceStatusOptions.java | 50 +
.../domain/options/ListInstancesOptions.java | 239 +
.../ecs/domain/options/ListVPCsOptions.java | 63 +
.../domain/options/ListVSwitchesOptions.java | 89 +
.../aliyun/ecs/domain/options/TagOptions.java | 22 +-
.../ecs/domain/regionscoped/ImageInRegion.java | 36 +
.../ecs/domain/regionscoped/RegionAndId.java | 54 +
.../aliyun/ecs/features/InstanceApi.java | 264 ++
.../aliyun/ecs/features/SecurityGroupApi.java | 3 +
.../aliyun/ecs/features/SshKeyPairApi.java | 4 +
.../org/jclouds/aliyun/ecs/features/TagApi.java | 10 +-
.../org/jclouds/aliyun/ecs/features/VPCApi.java | 140 +
.../jclouds/aliyun/ecs/features/VSwitchApi.java | 145 +
.../ecs/functions/PutStringInDoubleQuotes.java | 27 +
.../ecs/handlers/ECSErrorRetryHandler.java | 74 +
.../ecs/predicates/InstanceStatusPredicate.java | 33 +
.../ecs/compute/ECSComputeServiceLiveTest.java | 46 +
.../ecs/compute/ECSTemplateBuilderLiveTest.java | 53 +
.../ecs/compute/features/ImageApiLiveTest.java | 13 +-
.../ecs/compute/features/ImageApiMockTest.java | 19 +-
.../compute/features/InstanceApiLiveTest.java | 189 +
.../compute/features/InstanceApiMockTest.java | 168 +
.../features/RegionAndZoneApiMockTest.java | 9 +-
.../features/SecurityGroupApiLiveTest.java | 11 +-
.../features/SecurityGroupApiMockTest.java | 19 +-
.../compute/features/SshKeyPairApiLiveTest.java | 13 +-
.../compute/features/SshKeyPairApiMockTest.java | 21 +-
.../ecs/compute/features/TagApiLiveTest.java | 16 +-
.../ecs/compute/features/TagApiMockTest.java | 19 +-
.../ecs/compute/features/VPCApiLiveTest.java | 89 +
.../ecs/compute/features/VPCApiMockTest.java | 87 +
.../compute/features/VSwitchApiLiveTest.java | 100 +
.../compute/features/VSwitchApiMockTest.java | 87 +
.../functions/ImageInRegionToImageTest.java | 141 +
.../functions/InstanceStatusToStatusTest.java | 58 +
.../functions/InstanceToHardwareTest.java | 61 +
.../functions/InstanceToNodeMetadataTest.java | 249 +
.../BaseECSComputeServiceApiLiveTest.java | 22 +-
.../BaseECSComputeServiceApiMockTest.java | 5 +-
.../CreateResourcesThenCreateNodesTest.java | 395 ++
.../src/test/resources/availableZones.json | 423 ++
.../src/test/resources/instanceStatus.json | 18 +
.../src/test/resources/instanceTypes.json | 4281 ++++++++++++++++++
.../src/test/resources/instances-first.json | 960 ++++
.../src/test/resources/instances-last.json | 960 ++++
aliyun-ecs/src/test/resources/logback-test.xml | 42 +
.../src/test/resources/vpc-create-res.json | 6 +
.../src/test/resources/vpc-delete-res.json | 3 +
aliyun-ecs/src/test/resources/vpcs-first.json | 29 +
aliyun-ecs/src/test/resources/vpcs-last.json | 29 +
.../src/test/resources/vswitch-create-res.json | 4 +
.../src/test/resources/vswitch-delete-res.json | 3 +
.../src/test/resources/vswitches-first.json | 22 +
.../src/test/resources/vswitches-last.json | 22 +
100 files changed, 13485 insertions(+), 113 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/README.md
----------------------------------------------------------------------
diff --git a/aliyun-ecs/README.md b/aliyun-ecs/README.md
new file mode 100644
index 0000000..5bb8723
--- /dev/null
+++ b/aliyun-ecs/README.md
@@ -0,0 +1,43 @@
+alibaba Elastic Compute Service Provider
+==========================
+
+# How to use it
+
+alibaba ECS provider works exactly as any other jclouds provider.
+Notice that as alibaba supports dozens of locations and to limit the scope of some operations, one may want to use:
+
+and
+```bash
+jclouds.regions
+```
+which is by default `null`. If you want to target only the `north europe` region, you can use
+
+```bash
+jclouds.regions="eu-central-1"
+```
+
+# Setting Up Test Environment
+
+Get or create the `User Access Key` and `Access Key Secret` for your account at `https://usercenter.console.alibaba.com/#/manage/ak`
+
+# Run Live Tests
+
+Use the following to run one live test:
+
+```bash
+mvn -Dtest=<name of the live test> \
+ -Dtest.alibaba-ecs.identity="<AccessKey ID>" \
+ -Dtest.alibaba-ecs.credential="<Access Key Secret>"
+ integration-test -Plive
+```
+
+Use the following to run all the live tests:
+
+```bash
+
+mvn clean verify -Plive \
+ -Dtest.alibaba-ecs.identity="<AccessKey ID>" \
+ -Dtest.alibaba-ecs.credential="<Access Key Secret>"
+```
+
+
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/pom.xml
----------------------------------------------------------------------
diff --git a/aliyun-ecs/pom.xml b/aliyun-ecs/pom.xml
index da1b900..7b81aaf 100644
--- a/aliyun-ecs/pom.xml
+++ b/aliyun-ecs/pom.xml
@@ -32,8 +32,6 @@
<properties>
<test.aliyun-ecs.endpoint>https://ecs.aliyuncs.com/</test.aliyun-ecs.endpoint>
- <test.aliyun-ecs.api-version></test.aliyun-ecs.api-version>
- <test.aliyun-ecs.build-version/>
<test.aliyun-ecs.identity>FIXME_IDENTITY</test.aliyun-ecs.identity>
<test.aliyun-ecs.credential>FIXME_CREDENTIALS</test.aliyun-ecs.credential>
<test.aliyun-ecs.template/>
@@ -142,6 +140,5 @@
</profile>
</profiles>
-
</project>
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceApi.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceApi.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceApi.java
index bb24cf0..2b0c9f8 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceApi.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceApi.java
@@ -17,10 +17,13 @@
package org.jclouds.aliyun.ecs;
import org.jclouds.aliyun.ecs.features.ImageApi;
+import org.jclouds.aliyun.ecs.features.InstanceApi;
import org.jclouds.aliyun.ecs.features.RegionAndZoneApi;
import org.jclouds.aliyun.ecs.features.SecurityGroupApi;
import org.jclouds.aliyun.ecs.features.SshKeyPairApi;
import org.jclouds.aliyun.ecs.features.TagApi;
+import org.jclouds.aliyun.ecs.features.VPCApi;
+import org.jclouds.aliyun.ecs.features.VSwitchApi;
import org.jclouds.rest.annotations.Delegate;
import java.io.Closeable;
@@ -42,4 +45,12 @@ public interface ECSComputeServiceApi extends Closeable {
@Delegate
TagApi tagApi();
+ @Delegate
+ InstanceApi instanceApi();
+
+ @Delegate
+ VPCApi vpcApi();
+
+ @Delegate
+ VSwitchApi vSwitchApi();
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceProviderMetadata.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceProviderMetadata.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceProviderMetadata.java
index fbd7206..3ffed6d 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceProviderMetadata.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSComputeServiceProviderMetadata.java
@@ -51,8 +51,8 @@ public class ECSComputeServiceProviderMetadata extends BaseProviderMetadata {
public static class Builder extends BaseProviderMetadata.Builder {
protected Builder() {
- id("aliyun-ecs")
- .name("Alibaba Elastic Compute Service")
+ id("alibaba-ecs")
+ .name("Alibaba Cloud Elastic Compute Service")
.apiMetadata(new ECSServiceApiMetadata())
.homepage(URI.create("https://www.alibabacloud.com"))
.console(URI.create("https://ecs.console.aliyun.com"))
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSServiceApiMetadata.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSServiceApiMetadata.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSServiceApiMetadata.java
index d81ef96..54e725c 100644
--- a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSServiceApiMetadata.java
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/ECSServiceApiMetadata.java
@@ -18,6 +18,7 @@ package org.jclouds.aliyun.ecs;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Module;
+import org.jclouds.aliyun.ecs.compute.config.ECSServiceContextModule;
import org.jclouds.aliyun.ecs.config.ECSComputeServiceHttpApiModule;
import org.jclouds.aliyun.ecs.config.ECSComputeServiceParserModule;
import org.jclouds.apis.ApiMetadata;
@@ -46,7 +47,7 @@ public class ECSServiceApiMetadata extends BaseHttpApiMetadata<ECSComputeService
public static Properties defaultProperties() {
Properties properties = BaseHttpApiMetadata.defaultProperties();
- properties.put(TEMPLATE, "osFamily=CENTOS,os64Bit=true,osVersionMatches=7.4");
+ properties.put(TEMPLATE, "osFamily=CENTOS,os64Bit=true,osVersionMatches=7.*");
properties.put(TIMEOUT_NODE_RUNNING, 900000); // 15 mins
properties.put(TIMEOUT_NODE_SUSPENDED, 900000); // 15 mins
return properties;
@@ -60,7 +61,7 @@ public class ECSServiceApiMetadata extends BaseHttpApiMetadata<ECSComputeService
public static class Builder extends BaseHttpApiMetadata.Builder<ECSComputeServiceApi, Builder> {
protected Builder() {
- id("aliyun-ecs")
+ id("alibaba-ecs")
.name("Alibaba Elastic Compute Service API")
.identityName("user name")
.credentialName("user password")
@@ -72,6 +73,7 @@ public class ECSServiceApiMetadata extends BaseHttpApiMetadata<ECSComputeService
.defaultModules(ImmutableSet.<Class<? extends Module>>builder()
.add(ECSComputeServiceHttpApiModule.class)
.add(ECSComputeServiceParserModule.class)
+ .add(ECSServiceContextModule.class)
.build());
}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeService.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeService.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeService.java
new file mode 100644
index 0000000..b3c6802
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeService.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import org.jclouds.Constants;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.compute.strategy.CleanupResources;
+import org.jclouds.aliyun.ecs.domain.SecurityGroup;
+import org.jclouds.aliyun.ecs.domain.VSwitch;
+import org.jclouds.aliyun.ecs.domain.options.ListVSwitchesOptions;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.callables.RunScriptOnNode;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.extensions.ImageExtension;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.compute.extensions.internal.DelegatingImageExtension;
+import org.jclouds.compute.internal.BaseComputeService;
+import org.jclouds.compute.internal.PersistNodeCredentials;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
+import org.jclouds.compute.strategy.DestroyNodeStrategy;
+import org.jclouds.compute.strategy.GetImageStrategy;
+import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
+import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
+import org.jclouds.compute.strategy.ListNodesStrategy;
+import org.jclouds.compute.strategy.RebootNodeStrategy;
+import org.jclouds.compute.strategy.ResumeNodeStrategy;
+import org.jclouds.compute.strategy.SuspendNodeStrategy;
+import org.jclouds.domain.Credentials;
+import org.jclouds.domain.Location;
+import org.jclouds.scriptbuilder.functions.InitAdminAccess;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+
+@Singleton
+public class ECSComputeService extends BaseComputeService {
+ private final CleanupResources cleanupResources;
+
+ @Inject
+ protected ECSComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
+ @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
+ @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
+ GetImageStrategy getImageStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
+ CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
+ DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy startNodeStrategy,
+ SuspendNodeStrategy stopNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
+ @Named("DEFAULT") Provider<TemplateOptions> templateOptionsProvider,
+ @Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
+ @Named(TIMEOUT_NODE_TERMINATED) Predicate<AtomicReference<NodeMetadata>> nodeTerminated,
+ @Named(TIMEOUT_NODE_SUSPENDED) Predicate<AtomicReference<NodeMetadata>> nodeSuspended,
+ InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
+ RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
+ PersistNodeCredentials persistNodeCredentials,
+ @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+ CleanupResources cleanupResources, Optional<ImageExtension> imageExtension,
+ Optional<SecurityGroupExtension> securityGroupExtension,
+ DelegatingImageExtension.Factory delegatingImageExtension) {
+ super(context, credentialStore, images, sizes, locations, listNodesStrategy, getImageStrategy,
+ getNodeMetadataStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy,
+ startNodeStrategy, stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning,
+ nodeTerminated, nodeSuspended, initScriptRunnerFactory, initAdminAccess, runScriptOnNodeFactory,
+ persistNodeCredentials, userExecutor, imageExtension, securityGroupExtension, delegatingImageExtension);
+ this.cleanupResources = cleanupResources;
+ }
+
+ @Override
+ protected void cleanUpIncidentalResourcesOfDeadNodes(Set<? extends NodeMetadata> deadNodes) {
+ for (NodeMetadata deadNode : deadNodes) {
+ RegionAndId regionAndId = RegionAndId.fromSlashEncoded(deadNode.getId());
+ Set<String> tags = deadNode.getTags();
+ String vSwitchId = extractVSwitchId(tags);
+ VSwitch vSwitch = context.unwrapApi(ECSComputeServiceApi.class).vSwitchApi().list(deadNode.getLocation().getId(), ListVSwitchesOptions.Builder.vSwitchId(vSwitchId)).first().orNull();
+ String vpcId = vSwitch.vpcId();
+
+ try {
+ cleanupResources.cleanupNode(regionAndId);
+ } catch (Exception ex) {
+ logger.warn(ex, "Error cleaning up resources for node %s", deadNode);
+ }
+
+ List<SecurityGroup> securityGroups = cleanupResources.findOrphanedSecurityGroups(regionAndId.regionId(), deadNode.getGroup());
+ for (SecurityGroup securityGroup : securityGroups) {
+ logger.debug(">> destroying security group %s ...", securityGroup.id());
+ if (cleanupResources.cleanupSecurityGroupIfOrphaned(regionAndId.regionId(), securityGroup.id())) {
+ logger.debug(">> security group: (%s) has been deleted.", securityGroup.id());
+ } else {
+ logger.warn(">> security group: (%s) has not been deleted.", securityGroup.id());
+ }
+ }
+
+ // FIXME not sure it is correct to always delete vSwitch and VPC_PREFIX
+ logger.debug(">> destroying vSwitch %s ...", vSwitchId);
+ if (cleanupResources.cleanupVSwitchIfOrphaned(regionAndId.regionId(), vSwitchId)) {
+ logger.debug(">> vSwitch: (%s) has been deleted.", vSwitchId);
+ } else {
+ logger.warn(">> vSwitch: (%s) has not been deleted.", vSwitchId);
+ }
+
+ logger.debug(">> destroying vpc %s ...", vpcId);
+ try {
+ cleanupResources.cleanupVPCIfOrphaned(regionAndId.regionId(), vpcId);
+ logger.debug(">> VPC_PREFIX: (%s) has been deleted.", vpcId);
+ } catch (IllegalArgumentException e) {
+ logger.warn(">> VPC_PREFIX: (%s) has not been deleted.", vpcId);
+ }
+ }
+ }
+
+ private String extractVSwitchId(Set<String> tags) {
+ String vSwitchIdTag = Iterables.tryFind(tags, new Predicate<String>() {
+ @Override
+ public boolean apply(@Nullable String input) {
+ return input.startsWith("vsw-");
+ }
+ }).orNull();
+ return vSwitchIdTag;
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceAdapter.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceAdapter.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceAdapter.java
new file mode 100644
index 0000000..7e12ed8
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/ECSComputeServiceAdapter.java
@@ -0,0 +1,278 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.compute.strategy.CleanupResources;
+import org.jclouds.aliyun.ecs.domain.AvailableResource;
+import org.jclouds.aliyun.ecs.domain.AvailableZone;
+import org.jclouds.aliyun.ecs.domain.Image;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.InstanceRequest;
+import org.jclouds.aliyun.ecs.domain.InstanceType;
+import org.jclouds.aliyun.ecs.domain.Region;
+import org.jclouds.aliyun.ecs.domain.SupportedResource;
+import org.jclouds.aliyun.ecs.domain.options.CreateInstanceOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListImagesOptions;
+import org.jclouds.aliyun.ecs.domain.options.ListInstancesOptions;
+import org.jclouds.aliyun.ecs.domain.options.TagOptions;
+import org.jclouds.aliyun.ecs.domain.regionscoped.ImageInRegion;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.aliyun.ecs.compute.options.ECSServiceTemplateOptions;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.util.ComputeServiceUtils;
+import org.jclouds.logging.Logger;
+
+import javax.annotation.Nullable;
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Iterables.contains;
+import static com.google.common.collect.Lists.newArrayList;
+import static java.lang.String.format;
+import static org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId.fromSlashEncoded;
+import static org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId.slashEncodeRegionAndId;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+
+/**
+ * defines the connection between the {@link ECSComputeServiceApi} implementation and
+ * the jclouds {@link org.jclouds.compute.ComputeService}
+ */
+@Singleton
+public class ECSComputeServiceAdapter implements ComputeServiceAdapter<Instance, InstanceType, ImageInRegion, Region> {
+
+ private final ECSComputeServiceApi api;
+ private final Predicate<String> instanceSuspendedPredicate;
+
+ private final Supplier<Set<String>> regionIds;
+ private final CleanupResources cleanupResources;
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ ECSComputeServiceAdapter(ECSComputeServiceApi api,
+ @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> instanceSuspendedPredicate,
+ @org.jclouds.location.Region Supplier<Set<String>> regionIds,
+ CleanupResources cleanupResources) {
+ this.api = api;
+ this.instanceSuspendedPredicate = instanceSuspendedPredicate;
+ this.regionIds = regionIds;
+ this.cleanupResources = cleanupResources;
+ }
+
+ @Override
+ public NodeAndInitialCredentials<Instance> createNodeWithGroupEncodedIntoName(String group, String name, Template template) {
+ String instanceType = template.getHardware().getId();
+ String regionId = template.getLocation().getId();
+ String imageId = template.getImage().getId();
+
+ ECSServiceTemplateOptions templateOptions = template.getOptions().as(ECSServiceTemplateOptions.class);
+
+ String keyPairName = templateOptions.getKeyPairName();
+ String securityGroupId = Iterables.getOnlyElement(templateOptions.getGroups());
+ String vSwitchId = templateOptions.getVSwitchId();
+ Instance.InternetChargeType internetChargeType = Instance.InternetChargeType.fromValue(templateOptions.getInternetChargeType());
+ int internetMaxBandwidthOut = templateOptions.getInternetMaxBandwidthOut();
+ String instanceChargeType = templateOptions.getInstanceChargeType();
+
+ Map<String, String> tags = ComputeServiceUtils.metadataAndTagsAsValuesOfEmptyString(templateOptions);
+ tags = new ImmutableMap.Builder()
+ .putAll(tags)
+ .put(vSwitchId, "")
+ .build();
+ TagOptions tagOptions = TagOptions.Builder.tags(tags);
+
+ InstanceRequest instanceRequest = api.instanceApi().create(regionId, RegionAndId.fromSlashEncoded(imageId).id(), securityGroupId, name, instanceType,
+ CreateInstanceOptions.Builder
+ .vSwitchId(vSwitchId)
+ .internetChargeType(internetChargeType.toString())
+ .internetMaxBandwidthOut(internetMaxBandwidthOut)
+ .instanceChargeType(instanceChargeType)
+ .instanceName(name)
+ .keyPairName(keyPairName)
+ .tagOptions(tagOptions)
+ );
+
+ String regionAndInstanceId = slashEncodeRegionAndId(regionId, instanceRequest.getInstanceId());
+ if (!instanceSuspendedPredicate.apply(regionAndInstanceId)) {
+ final String message = format("Instance %s was not created correctly. The associated resources created for it will be destroyed", instanceRequest.getInstanceId());
+ logger.warn(message);
+ cleanupResources.cleanupNode(RegionAndId.create(regionId, instanceRequest.getInstanceId()));
+ cleanupResources.cleanupSecurityGroupIfOrphaned(regionId, securityGroupId);
+ }
+
+ api.instanceApi().allocatePublicIpAddress(regionId, instanceRequest.getInstanceId());
+ api.instanceApi().powerOn(instanceRequest.getInstanceId());
+ Instance instance = Iterables.get(api.instanceApi().list(regionId, ListInstancesOptions.Builder.instanceIds(instanceRequest.getInstanceId())), 0);
+
+ // Safe to pass null credentials here, as jclouds will default populate
+ // the node with the default credentials from the image, or the ones in
+ // the options, if provided.
+ return new NodeAndInitialCredentials(instance,
+ slashEncodeRegionAndId(regionId, instanceRequest.getInstanceId()), null);
+ }
+
+ @Override
+ public Iterable<InstanceType> listHardwareProfiles() {
+ final ImmutableSet.Builder<String> instanceTypeIdsBuilder = ImmutableSet.builder();
+ for (String regionId : getAvailableLocationNames()) {
+ instanceTypeIdsBuilder.addAll(getInstanceTypeIds(regionId));
+ }
+ final Set<String> ids = instanceTypeIdsBuilder.build();
+
+ List<InstanceType> instanceTypes = FluentIterable.from(api.instanceApi().listTypes())
+ .filter(new Predicate<InstanceType>() {
+ @Override
+ public boolean apply(@Nullable InstanceType input) {
+ return contains(ids, input.id());
+ }
+ }).toList();
+
+ return instanceTypes;
+ }
+
+ private List<String> getInstanceTypeIds(String regionId) {
+ List<String> instanceTypeIds = Lists.newArrayList();
+ for (AvailableZone availableZone : api.instanceApi().listInstanceTypesByAvailableZone(regionId)) {
+ for (AvailableResource availableResource : availableZone.availableResources().get("AvailableResource")) {
+ for (SupportedResource supportedResource : availableResource.supportedResources()
+ .get("SupportedResource")) {
+ if (SupportedResource.Status.AVAILABLE == supportedResource.status()) {
+ instanceTypeIds.add(supportedResource.value());
+ }
+ }
+ }
+ }
+ return instanceTypeIds;
+ }
+
+ @Override
+ public Iterable<ImageInRegion> listImages() {
+ final ImmutableList.Builder<ImageInRegion> imagesInRegion = ImmutableList.builder();
+
+ for (final String regionId : getAvailableLocationNames()) {
+ imagesInRegion.addAll(api.imageApi().list(regionId).concat()
+ .transform(new Function<Image, ImageInRegion>() {
+ @Override
+ public ImageInRegion apply(Image image) {
+ return ImageInRegion.create(regionId, image);
+ }
+ })
+ );
+ }
+ return imagesInRegion.build();
+ }
+
+ @Override
+ public ImageInRegion getImage(final String id) {
+ RegionAndId regionAndId = fromSlashEncoded(id);
+ Image image = api.imageApi().list(regionAndId.regionId(), ListImagesOptions.Builder.imageIds(regionAndId.id()))
+ .firstMatch(Predicates.<Image>notNull())
+ .orNull();
+ if (image == null) return null;
+ return ImageInRegion.create(regionAndId.regionId(), image);
+ }
+
+ @Override
+ public Iterable<Region> listLocations() {
+ return FluentIterable.from(api.regionAndZoneApi().describeRegions()).filter(new Predicate<Region>() {
+ @Override
+ public boolean apply(Region region) {
+ return regionIds.get().isEmpty() ? true : regionIds.get().contains(region.id());
+ }
+ }).toList();
+ }
+
+ @Override
+ public Instance getNode(final String id) {
+ RegionAndId regionAndId = fromSlashEncoded(id);
+ return api.instanceApi().list(regionAndId.regionId(),
+ ListInstancesOptions.Builder.instanceIds(regionAndId.id()))
+ .firstMatch(Predicates.<Instance>notNull())
+ .orNull();
+ }
+
+ @Override
+ public void destroyNode(String id) {
+ checkState(cleanupResources.cleanupNode(RegionAndId.fromSlashEncoded(id)), "server(%s) and its resources still there after deleting!?", id);
+ }
+
+ @Override
+ public void rebootNode(String id) {
+ api.instanceApi().reboot(id);
+ }
+
+ @Override
+ public void resumeNode(String id) {
+ api.instanceApi().powerOn(id);
+ }
+
+ @Override
+ public void suspendNode(String id) {
+ api.instanceApi().powerOff(id);
+ }
+
+ @Override
+ public Iterable<Instance> listNodes() {
+ final ImmutableList.Builder<Instance> instances = ImmutableList.builder();
+ for (String regionId : getAvailableLocationNames()) {
+ instances.addAll(api.instanceApi().list(regionId).concat());
+ }
+ return instances.build();
+ }
+
+ @Override
+ public Iterable<Instance> listNodesByIds(final Iterable<String> ids) {
+
+ final ImmutableList.Builder<Instance> instancesBuilder = ImmutableList.builder();
+ for (String regionId : getAvailableLocationNames()) {
+ instancesBuilder.addAll(api.instanceApi().list(regionId, ListInstancesOptions.Builder.instanceIds(Iterables.toArray(ids, String.class))));
+ }
+ return instancesBuilder.build();
+ }
+
+ private List<String> getAvailableLocationNames() {
+ return newArrayList(
+ Iterables.transform(listLocations(), new Function<Region, String>() {
+ @Override
+ public String apply(Region location) {
+ return location.id();
+ }
+ }));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/config/ECSServiceContextModule.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/config/ECSServiceContextModule.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/config/ECSServiceContextModule.java
new file mode 100644
index 0000000..ace98e9
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/config/ECSServiceContextModule.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.config;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+import com.google.inject.name.Named;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.compute.ECSComputeService;
+import org.jclouds.aliyun.ecs.compute.ECSComputeServiceAdapter;
+import org.jclouds.aliyun.ecs.compute.functions.ImageInRegionToImage;
+import org.jclouds.aliyun.ecs.compute.functions.InstanceStatusToStatus;
+import org.jclouds.aliyun.ecs.compute.functions.InstanceToNodeMetadata;
+import org.jclouds.aliyun.ecs.compute.functions.InstanceTypeToHardware;
+import org.jclouds.aliyun.ecs.compute.functions.RegionToLocation;
+import org.jclouds.aliyun.ecs.compute.strategy.CreateResourcesThenCreateNodes;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.InstanceStatus;
+import org.jclouds.aliyun.ecs.domain.InstanceType;
+import org.jclouds.aliyun.ecs.domain.Region;
+import org.jclouds.aliyun.ecs.domain.regionscoped.ImageInRegion;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.aliyun.ecs.compute.options.ECSServiceTemplateOptions;
+import org.jclouds.aliyun.ecs.predicates.InstanceStatusPredicate;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.ComputeServiceAdapter;
+import org.jclouds.compute.config.ComputeServiceAdapterContextModule;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatement;
+import org.jclouds.compute.functions.NodeAndTemplateOptionsToStatementWithoutPublicKey;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
+import org.jclouds.domain.Location;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_RUNNING;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+import static org.jclouds.util.Predicates2.retry;
+
+public class ECSServiceContextModule extends ComputeServiceAdapterContextModule<Instance, InstanceType, ImageInRegion, Region> {
+
+ @Override
+ protected void configure() {
+ super.configure();
+
+ bind(new TypeLiteral<ComputeServiceAdapter<Instance, InstanceType, ImageInRegion, Region>>() {
+ }).to(ECSComputeServiceAdapter.class);
+ bind(ComputeService.class).to(ECSComputeService.class);
+
+ bind(new TypeLiteral<Function<Instance, NodeMetadata>>() {
+ }).to(InstanceToNodeMetadata.class);
+ bind(new TypeLiteral<Function<InstanceType, Hardware>>() {
+ }).to(InstanceTypeToHardware.class);
+ bind(new TypeLiteral<Function<ImageInRegion, org.jclouds.compute.domain.Image>>() {
+ }).to(ImageInRegionToImage.class);
+ bind(new TypeLiteral<Function<Region, Location>>() {
+ }).to(RegionToLocation.class);
+ bind(new TypeLiteral<Function<Instance.Status, NodeMetadata.Status>>() {
+ }).to(InstanceStatusToStatus.class);
+ install(new LocationsFromComputeServiceAdapterModule<Instance, InstanceType, ImageInRegion, Region>() {
+ });
+ bind(TemplateOptions.class).to(ECSServiceTemplateOptions.class);
+ bind(CreateNodesInGroupThenAddToSet.class).to(CreateResourcesThenCreateNodes.class);
+ bind(NodeAndTemplateOptionsToStatement.class).to(NodeAndTemplateOptionsToStatementWithoutPublicKey.class);
+ }
+
+ @Provides
+ @Named(TIMEOUT_NODE_RUNNING)
+ protected Predicate<String> provideInstanceRunningPredicate(final ECSComputeServiceApi api,
+ ComputeServiceConstants.Timeouts timeouts, ComputeServiceConstants.PollPeriod pollPeriod) {
+ return retry(new InstanceInStatusPredicate(api, InstanceStatus.Status.RUNNING), timeouts.nodeRunning,
+ pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+ }
+
+ @Provides
+ @Named(TIMEOUT_NODE_SUSPENDED)
+ protected Predicate<String> provideInstanceSuspendedPredicate(final ECSComputeServiceApi api,
+ ComputeServiceConstants.Timeouts timeouts, ComputeServiceConstants.PollPeriod pollPeriod) {
+ return retry(new InstanceInStatusPredicate(api, InstanceStatus.Status.STOPPED), timeouts.nodeSuspended,
+ pollPeriod.pollInitialPeriod, pollPeriod.pollMaxPeriod);
+ }
+
+ @Provides
+ @Named(TIMEOUT_NODE_TERMINATED)
+ protected Predicate<String> provideInstanceTerminatedPredicate(final ECSComputeServiceApi api,
+ ComputeServiceConstants.Timeouts timeouts, ComputeServiceConstants.PollPeriod pollPeriod) {
+ return retry(new InstanceTerminatedPredicate(api), timeouts.nodeTerminated, pollPeriod.pollInitialPeriod,
+ pollPeriod.pollMaxPeriod);
+ }
+
+ @VisibleForTesting
+ static class InstanceInStatusPredicate implements Predicate<String> {
+
+ private final ECSComputeServiceApi api;
+ private final InstanceStatus.Status desiredStatus;
+
+ public InstanceInStatusPredicate(ECSComputeServiceApi api, InstanceStatus.Status desiredStatus) {
+ this.api = checkNotNull(api, "api must not be null");
+ this.desiredStatus = checkNotNull(desiredStatus, "instance status must not be null");
+ }
+
+ @Override
+ public boolean apply(String id) {
+ checkNotNull(id, "id");
+ RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
+ String regionId = regionAndId.regionId();
+ String instanceId = regionAndId.id();
+ InstanceStatus instanceStatus = api.instanceApi().listInstanceStatus(regionId)
+ .concat()
+ .firstMatch(new InstanceStatusPredicate(instanceId))
+ .orNull();
+ return instanceStatus != null && desiredStatus == instanceStatus.status();
+ }
+ }
+
+ @VisibleForTesting
+ static class InstanceTerminatedPredicate implements Predicate<String> {
+
+ private final ECSComputeServiceApi api;
+
+ public InstanceTerminatedPredicate(ECSComputeServiceApi api) {
+ this.api = checkNotNull(api, "api must not be null");
+ }
+
+ @Override
+ public boolean apply(String id) {
+ checkNotNull(id, "id");
+ RegionAndId regionAndId = RegionAndId.fromSlashEncoded(id);
+ String regionId = regionAndId.regionId();
+ final String instanceId = regionAndId.id();
+ InstanceStatus instanceStatus = api.instanceApi().listInstanceStatus(regionId)
+ .concat()
+ .firstMatch(new InstanceStatusPredicate(instanceId))
+ .orNull();
+ return instanceStatus == null;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImage.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImage.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImage.java
new file mode 100644
index 0000000..72c45cf
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/ImageInRegionToImage.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Inject;
+import org.jclouds.aliyun.ecs.compute.functions.internal.OperatingSystems;
+import org.jclouds.aliyun.ecs.domain.regionscoped.ImageInRegion;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.domain.Location;
+import org.jclouds.location.predicates.LocationPredicates;
+
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Iterables.tryFind;
+import static java.util.Arrays.asList;
+import static org.jclouds.compute.domain.OperatingSystem.builder;
+
+public class ImageInRegionToImage implements Function<ImageInRegion, Image> {
+
+ private final Supplier<Set<? extends Location>> locations;
+
+ private static final Map<String, OsFamily> OTHER_OS_MAP = ImmutableMap.<String, OsFamily>builder()
+ .put("Aliyun", OsFamily.LINUX).build();
+
+ private static Optional<OsFamily> findInStandardFamilies(final String platform) {
+ return tryFind(asList(OsFamily.values()), new Predicate<OsFamily>() {
+ @Override
+ public boolean apply(OsFamily input) {
+ return platform.toUpperCase().startsWith(input.name());
+ }
+ });
+ }
+
+ private static Optional<OsFamily> findInOtherOSMap(final String label) {
+ return tryFind(OTHER_OS_MAP.keySet(), new Predicate<String>() {
+ @Override
+ public boolean apply(String input) {
+ return label.contains(input);
+ }
+ }).transform(new Function<String, OsFamily>() {
+ @Override
+ public OsFamily apply(String input) {
+ return OTHER_OS_MAP.get(input);
+ }
+ });
+ }
+
+ @Inject
+ ImageInRegionToImage(@Memoized Supplier<Set<? extends Location>> locations) {
+ this.locations = locations;
+ }
+
+ @Override
+ public Image apply(ImageInRegion from) {
+ ImageBuilder builder = new ImageBuilder();
+ builder.id(RegionAndId.slashEncodeRegionAndId(from.regionId(), from.image().id()));
+ builder.providerId(from.image().id());
+ builder.name(from.image().name());
+ builder.description(from.image().description());
+ builder.status(from.image().status() == org.jclouds.aliyun.ecs.domain.Image.Status.AVAILABLE ?
+ Image.Status.AVAILABLE : Image.Status.PENDING);
+
+ OsFamily family = findInStandardFamilies(from.image().platform())
+ .or(findInOtherOSMap(from.image().platform()))
+ .or(OsFamily.UNRECOGNIZED);
+
+ String osVersion = OperatingSystems.version().apply(from.image());
+
+ builder.operatingSystem(
+ builder().name(from.image().osName()).family(family)
+ .description(from.image().description())
+ .version(osVersion)
+ .is64Bit("x86_64".equals(from.image().architecture()) ? true : false).build());
+
+ builder.location(from(locations.get()).firstMatch(LocationPredicates.idEquals(from.regionId())).orNull());
+ return builder.build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatus.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatus.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatus.java
new file mode 100644
index 0000000..8fcaf18
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceStatusToStatus.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Function;
+import com.google.common.base.Functions;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.compute.domain.NodeMetadata;
+
+import javax.inject.Singleton;
+
+/**
+ * Transforms an {@link Instance.Status} to the jclouds portable model.
+ */
+@Singleton
+public class InstanceStatusToStatus implements Function<Instance.Status, NodeMetadata.Status> {
+
+ private static final Function<Instance.Status, NodeMetadata.Status> toPortableStatus = Functions.forMap(
+ ImmutableMap.<Instance.Status, NodeMetadata.Status>builder()
+ .put(Instance.Status.STARTING, NodeMetadata.Status.PENDING)
+ .put(Instance.Status.STOPPING, NodeMetadata.Status.PENDING)
+ .put(Instance.Status.STOPPED, NodeMetadata.Status.SUSPENDED)
+ .put(Instance.Status.RUNNING, NodeMetadata.Status.RUNNING).build(), NodeMetadata.Status.UNRECOGNIZED);
+
+ @Override
+ public NodeMetadata.Status apply(Instance.Status input) {
+ return toPortableStatus.apply(input);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadata.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadata.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadata.java
new file mode 100644
index 0000000..1ead7ce
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceToNodeMetadata.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import org.jclouds.aliyun.ecs.domain.Instance;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.collect.Memoized;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.functions.GroupNamingConvention;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.domain.Location;
+import org.jclouds.location.predicates.LocationPredicates;
+import org.jclouds.logging.Logger;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.jclouds.compute.util.ComputeServiceUtils.addMetadataAndParseTagsFromValuesOfEmptyString;
+
+/**
+ * Transforms an {@link Instance} to the jclouds portable model.
+ */
+@Singleton
+public class InstanceToNodeMetadata implements Function<Instance, NodeMetadata> {
+
+ private final Supplier<Map<String, ? extends Image>> images;
+ private final Supplier<Map<String, ? extends Hardware>> hardwares;
+ private final Supplier<Set<? extends Location>> locations;
+ private final Function<Instance.Status, NodeMetadata.Status> toPortableStatus;
+ private final GroupNamingConvention groupNamingConvention;
+
+ @Resource @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ @Inject
+ InstanceToNodeMetadata(Supplier<Map<String, ? extends Image>> images,
+ Supplier<Map<String, ? extends Hardware>> hardwares,
+ @Memoized Supplier<Set<? extends Location>> locations,
+ Function<Instance.Status, NodeMetadata.Status> toPortableStatus,
+ GroupNamingConvention.Factory groupNamingConvention) {
+ this.images = images;
+ this.hardwares = hardwares;
+ this.locations = locations;
+ this.toPortableStatus = toPortableStatus;
+ this.groupNamingConvention = groupNamingConvention.createWithoutPrefix();
+ }
+
+ @Override
+ public NodeMetadata apply(Instance from) {
+ NodeMetadataBuilder builder = new NodeMetadataBuilder();
+
+ Optional<? extends Image> image = findImage(from.imageId());
+ if (image.isPresent()) {
+ builder.imageId(image.get().getId());
+ builder.operatingSystem(image.get().getOperatingSystem());
+ } else {
+ logger.info(">> image with id %s for instance %s was not found. "
+ + "This might be because the image that was used to create the instance has a new id.",
+ from.instanceType(), from.id());
+ }
+ Optional<? extends Hardware> hardware = findHardware(from.instanceType());
+ if (hardware.isPresent()) {
+ builder.hardware(hardware.get());
+ } else {
+ logger.info(">> hardware with id %s for instance %s was not found. "
+ + "This might be because the image that was used to create the instance has a new id.",
+ from.instanceType(), from.id());
+ }
+
+ builder.id(RegionAndId.slashEncodeRegionAndId(from.regionId(), from.id()));
+ builder.providerId(from.id());
+ builder.name(from.name());
+ builder.hostname(String.format("%s", from.hostname()));
+ builder.group(groupNamingConvention.extractGroup(from.name()));
+ builder.status(toPortableStatus.apply(from.status()));
+ builder.privateAddresses(from.innerIpAddress().entrySet().iterator().next().getValue());
+ builder.publicAddresses(from.publicIpAddress().entrySet().iterator().next().getValue());
+ builder.location(from(locations.get()).firstMatch(LocationPredicates.idEquals(from.regionId())).orNull());
+ if (from.tags() != null && !from.tags().isEmpty()) {
+ ImmutableMap.Builder tagsBuilder = new ImmutableMap.Builder();
+ for (Tag tag : from.tags().entrySet().iterator().next().getValue()) {
+ tagsBuilder.put(tag.key(), tag.value());
+ }
+ addMetadataAndParseTagsFromValuesOfEmptyString(builder, tagsBuilder.build());
+ }
+
+ NodeMetadata nodeMetadata = builder.build();
+ return nodeMetadata;
+ }
+
+ private Optional<? extends Image> findImage(String imageId) {
+ return Optional.fromNullable(images.get().get(imageId));
+ }
+
+ private Optional<? extends Hardware> findHardware(String instanceType) {
+ return Optional.fromNullable(hardwares.get().get(instanceType));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceTypeToHardware.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceTypeToHardware.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceTypeToHardware.java
new file mode 100644
index 0000000..8197979
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/InstanceTypeToHardware.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import org.jclouds.aliyun.ecs.domain.InstanceType;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Processor;
+
+import javax.inject.Singleton;
+
+@Singleton
+public class InstanceTypeToHardware implements Function<InstanceType, Hardware> {
+
+ private static final int GB_TO_MB_MULTIPLIER = 1024;
+
+ @Override
+ public Hardware apply(InstanceType input) {
+ HardwareBuilder builder = new HardwareBuilder()
+ .ids(input.id())
+ .name(input.id())
+ .hypervisor("none")
+ .processors(getProcessors(input.cpuCoreCount()))
+ .ram(input.memorySize().intValue() * GB_TO_MB_MULTIPLIER);
+ return builder.build();
+ }
+
+ private Iterable<Processor> getProcessors(Integer cpuCoreCount) {
+ // No cpu speed from API, so assume more cores == faster
+ return ImmutableList.of(new Processor(cpuCoreCount, cpuCoreCount));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/RegionToLocation.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/RegionToLocation.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/RegionToLocation.java
new file mode 100644
index 0000000..2bca519
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/RegionToLocation.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions;
+
+import com.google.common.base.Function;
+import org.jclouds.aliyun.ecs.domain.Region;
+import org.jclouds.domain.Location;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.domain.LocationScope;
+import org.jclouds.location.suppliers.all.JustProvider;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+
+/**
+ * Transforms an {@link Region} to the jclouds portable model.
+ */
+@Singleton
+public class RegionToLocation implements Function<Region, Location> {
+
+ private final JustProvider justProvider;
+
+ // allow us to lazy discover the provider of a resource
+ @Inject
+ RegionToLocation(JustProvider justProvider) {
+ this.justProvider = justProvider;
+ }
+
+ @Override
+ public Location apply(final Region region) {
+ final LocationBuilder builder = new LocationBuilder();
+ builder.id(region.id());
+ builder.description(region.localName());
+ builder.parent(getOnlyElement(justProvider.get()));
+ builder.scope(LocationScope.REGION);
+ return builder.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/internal/OperatingSystems.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/internal/OperatingSystems.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/internal/OperatingSystems.java
new file mode 100644
index 0000000..93681b2
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/functions/internal/OperatingSystems.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.functions.internal;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
+import org.jclouds.aliyun.ecs.domain.Image;
+import org.jclouds.compute.domain.OsFamily;
+
+public class OperatingSystems {
+
+ public static Function<Image, String> version() {
+ return new Function<Image, String>() {
+ @Override
+ public String apply(final Image image) {
+ return parseVersion(image);
+ }
+ };
+ }
+
+ private static String parseVersion(Image image) {
+ String sequence = image.osName().trim().replaceAll("\\s+", " ");
+ int offset = 2;
+ if (isWindows(image)) {
+ sequence = image.platform();
+ offset = 1;
+ }
+ Iterable<String> splitted = Splitter.on(" ").split(sequence);
+ return Iterables.get(splitted, Iterables.size(splitted) - offset);
+ }
+
+ public static boolean isWindows(Image image) {
+ return image.platform().toUpperCase().startsWith(OsFamily.WINDOWS.name());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/options/ECSServiceTemplateOptions.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/options/ECSServiceTemplateOptions.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/options/ECSServiceTemplateOptions.java
new file mode 100644
index 0000000..c378cbd
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/options/ECSServiceTemplateOptions.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.options;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.jclouds.compute.options.TemplateOptions;
+
+import static com.google.common.base.Objects.equal;
+
+/**
+ * Custom options for the Alibaba Elastic Compute Service API.
+ */
+public class ECSServiceTemplateOptions extends TemplateOptions implements Cloneable {
+
+ private String keyPairName = "";
+ private String vSwitchId = "";
+ private String internetChargeType = "PayByTraffic";
+ private String instanceChargeType = "PostPaid";
+ private int internetMaxBandwidthOut = 5;
+
+ public ECSServiceTemplateOptions keyPairName(String keyPairName) {
+ this.keyPairName = keyPairName;
+ return this;
+ }
+
+ public ECSServiceTemplateOptions vSwitchId(String vSwitchId) {
+ this.vSwitchId = vSwitchId;
+ return this;
+ }
+
+ public ECSServiceTemplateOptions internetChargeType(String internetChargeType) {
+ this.internetChargeType = internetChargeType;
+ return this;
+ }
+
+ public ECSServiceTemplateOptions instanceChargeType(String instanceChargeType) {
+ this.instanceChargeType = instanceChargeType;
+ return this;
+ }
+
+ public ECSServiceTemplateOptions internetMaxBandwidthOut(int internetMaxBandwidthOut) {
+ this.internetMaxBandwidthOut = internetMaxBandwidthOut;
+ return this;
+ }
+
+ public String getKeyPairName() {
+ return keyPairName;
+ }
+
+ public String getVSwitchId() {
+ return vSwitchId;
+ }
+
+ public String getInternetChargeType() {
+ return internetChargeType;
+ }
+
+ public String getInstanceChargeType() {
+ return instanceChargeType;
+ }
+
+ public int getInternetMaxBandwidthOut() {
+ return internetMaxBandwidthOut;
+ }
+
+ @Override
+ public ECSServiceTemplateOptions clone() {
+ ECSServiceTemplateOptions options = new ECSServiceTemplateOptions();
+ copyTo(options);
+ return options;
+ }
+
+ @Override
+ public void copyTo(TemplateOptions to) {
+ super.copyTo(to);
+ if (to instanceof ECSServiceTemplateOptions) {
+ ECSServiceTemplateOptions eTo = ECSServiceTemplateOptions.class.cast(to);
+ eTo.keyPairName(keyPairName);
+ eTo.vSwitchId(vSwitchId);
+ eTo.internetChargeType(internetChargeType);
+ eTo.instanceChargeType(instanceChargeType);
+ eTo.internetMaxBandwidthOut(internetMaxBandwidthOut);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(super.hashCode(), keyPairName, vSwitchId, internetChargeType, instanceChargeType, internetMaxBandwidthOut);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ECSServiceTemplateOptions other = (ECSServiceTemplateOptions) obj;
+ return super.equals(other) &&
+ equal(this.keyPairName, other.keyPairName) &&
+ equal(this.vSwitchId, other.vSwitchId) &&
+ equal(this.internetChargeType, other.internetChargeType) &&
+ equal(this.instanceChargeType, other.instanceChargeType) &&
+ equal(this.internetMaxBandwidthOut, other.internetMaxBandwidthOut);
+ }
+
+ @Override
+ public MoreObjects.ToStringHelper string() {
+ MoreObjects.ToStringHelper toString = super.string().omitNullValues();
+ toString.add("keyPairName", keyPairName);
+ toString.add("vSwitchId", vSwitchId);
+ toString.add("internetChargeType", internetChargeType);
+ toString.add("instanceChargeType", instanceChargeType);
+ toString.add("internetMaxBandwidthOut", internetMaxBandwidthOut);
+ return toString;
+ }
+
+ public static class Builder {
+
+ /**
+ * @see ECSServiceTemplateOptions#keyPairName
+ */
+ public static ECSServiceTemplateOptions keyPairName(String keyPairName) {
+ ECSServiceTemplateOptions options = new ECSServiceTemplateOptions();
+ return options.keyPairName(keyPairName);
+ }
+
+ /**
+ * @see ECSServiceTemplateOptions#vSwitchId
+ */
+ public static ECSServiceTemplateOptions vSwitchId(String vSwitchId) {
+ ECSServiceTemplateOptions options = new ECSServiceTemplateOptions();
+ return options.vSwitchId(vSwitchId);
+ }
+
+ /**
+ * @see ECSServiceTemplateOptions#internetChargeType
+ */
+ public static ECSServiceTemplateOptions internetChargeType(String internetChargeType) {
+ ECSServiceTemplateOptions options = new ECSServiceTemplateOptions();
+ return options.internetChargeType(internetChargeType);
+ }
+
+ /**
+ * @see ECSServiceTemplateOptions#instanceChargeType
+ */
+ public static ECSServiceTemplateOptions instanceChargeType(String instanceChargeType) {
+ ECSServiceTemplateOptions options = new ECSServiceTemplateOptions();
+ return options.instanceChargeType(instanceChargeType);
+ }
+
+ /**
+ * @see ECSServiceTemplateOptions#internetMaxBandwidthOut
+ */
+ public static ECSServiceTemplateOptions internetMaxBandwidthOut(int internetMaxBandwidthOut) {
+ ECSServiceTemplateOptions options = new ECSServiceTemplateOptions();
+ return options.internetMaxBandwidthOut(internetMaxBandwidthOut);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds-labs/blob/2c7db7e8/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CleanupResources.java
----------------------------------------------------------------------
diff --git a/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CleanupResources.java b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CleanupResources.java
new file mode 100644
index 0000000..8fb5730
--- /dev/null
+++ b/aliyun-ecs/src/main/java/org/jclouds/aliyun/ecs/compute/strategy/CleanupResources.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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
+ *
+ * http://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.
+ */
+package org.jclouds.aliyun.ecs.compute.strategy;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import org.jclouds.aliyun.ecs.ECSComputeServiceApi;
+import org.jclouds.aliyun.ecs.domain.InstanceStatus;
+import org.jclouds.aliyun.ecs.domain.SecurityGroup;
+import org.jclouds.aliyun.ecs.domain.Tag;
+import org.jclouds.aliyun.ecs.domain.regionscoped.RegionAndId;
+import org.jclouds.aliyun.ecs.predicates.InstanceStatusPredicate;
+import org.jclouds.compute.reference.ComputeServiceConstants;
+import org.jclouds.logging.Logger;
+
+import javax.annotation.Nullable;
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+import java.util.List;
+
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_SUSPENDED;
+import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_TERMINATED;
+
+/**
+ * This utility takes care of cleaning up all the resources created to deploy the node
+ *
+ * Specifically, it tries to delete the security group created for the group of nodes.
+ * In case a VPC_PREFIX and a vSwitch were created for the node, it tries to remove them
+ */
+@Singleton
+public class CleanupResources {
+
+ @Resource
+ @Named(ComputeServiceConstants.COMPUTE_LOGGER)
+ protected Logger logger = Logger.NULL;
+
+ private final ECSComputeServiceApi api;
+ private final Predicate<String> instanceSuspendedPredicate;
+ private final Predicate<String> instanceTerminatedPredicate;
+
+ @Inject
+ public CleanupResources(ECSComputeServiceApi api,
+ @Named(TIMEOUT_NODE_SUSPENDED) Predicate<String> instanceSuspendedPredicate,
+ @Named(TIMEOUT_NODE_TERMINATED) Predicate<String> instanceTerminatedPredicate
+ ) {
+ this.api = api;
+ this.instanceSuspendedPredicate = instanceSuspendedPredicate;
+ this.instanceTerminatedPredicate = instanceTerminatedPredicate;
+ }
+
+ /**
+ * @param regionAndId
+ * @return whether the node and its resources have been deleted
+ */
+ public boolean cleanupNode(final RegionAndId regionAndId) {
+ String instanceId = regionAndId.id();
+ InstanceStatus instanceStatus = Iterables.tryFind(api.instanceApi().listInstanceStatus(regionAndId.regionId()).concat(),
+ new InstanceStatusPredicate(instanceId)).orNull();
+ if (instanceStatus == null) return true;
+ if (InstanceStatus.Status.STOPPED != instanceStatus.status()) {
+ logger.debug(">> powering off %s ...", RegionAndId.slashEncodeRegionAndId(regionAndId));
+ api.instanceApi().powerOff(instanceId);
+ instanceSuspendedPredicate.apply(RegionAndId.slashEncodeRegionAndId(regionAndId));
+ }
+ logger.debug(">> destroying %s ...", RegionAndId.slashEncodeRegionAndId(regionAndId));
+ api.instanceApi().delete(instanceId);
+ return instanceTerminatedPredicate.apply(RegionAndId.slashEncodeRegionAndId(regionAndId));
+ }
+
+ public List<SecurityGroup> findOrphanedSecurityGroups(final String regionId, final String group) {
+ return api.securityGroupApi().list(regionId).concat().filter(new Predicate<SecurityGroup>() {
+ @Override
+ public boolean apply(@Nullable SecurityGroup input) {
+ List<Tag> actual = input.tags().entrySet().iterator().next().getValue();
+ List<Tag> expected = ImmutableList.of(
+ Tag.create(Tag.DEFAULT_OWNER_KEY, Tag.DEFAULT_OWNER_VALUE), Tag.create(Tag.GROUP, group)
+ );
+ return actual.containsAll(expected) && expected.containsAll(actual);
+ }
+ }).toList();
+ }
+
+ public boolean cleanupSecurityGroupIfOrphaned(final String regionId, String securityGroupId) {
+ return api.securityGroupApi().delete(regionId, securityGroupId) != null;
+ }
+
+ public boolean cleanupVSwitchIfOrphaned(final String regionId, String vSwitchId) {
+ return api.vSwitchApi().delete(regionId, vSwitchId) != null;
+ }
+
+ public boolean cleanupVPCIfOrphaned(final String regionId, String vpcId) {
+ return api.vpcApi().delete(regionId, vpcId) != null;
+ }
+
+}