feat(region): aws nat gateway read

This commit is contained in:
ioito
2021-12-13 16:37:35 +08:00
parent 5f58994459
commit dbaab28274
15 changed files with 755 additions and 459 deletions
+7
View File
@@ -104,3 +104,10 @@ type ElasticipAssociateInput struct {
// default: server
InstanceType string `json:"instance_type"`
}
type ElasticDissociateInput struct {
// 注意: 若关联到aws NAT网关后,目前没办法解除关联关系
// 是否解绑后自动删除弹性公网IP
// default: false
AutoDelete bool `json:"auto_delete"`
}
+2 -4
View File
@@ -1087,7 +1087,7 @@ func (self *SElasticip) StartEipAssociateTask(ctx context.Context, userCred mccl
return task.ScheduleRun(nil)
}
func (self *SElasticip) PerformDissociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
func (self *SElasticip) PerformDissociate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ElasticDissociateInput) (jsonutils.JSONObject, error) {
if len(self.AssociateId) == 0 {
return nil, nil // success
}
@@ -1111,9 +1111,7 @@ func (self *SElasticip) PerformDissociate(ctx context.Context, userCred mcclient
return nil, httperrors.NewUnsupportOperationError("fixed public eip cannot be dissociated")
}
autoDelete := jsonutils.QueryBoolean(data, "auto_delete", false)
err = self.StartEipDissociateTask(ctx, userCred, autoDelete, "")
err = self.StartEipDissociateTask(ctx, userCred, input.AutoDelete, "")
return nil, err
}
+2 -1
View File
@@ -10,11 +10,12 @@ package apis
import (
context "context"
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
-95
View File
@@ -23,14 +23,10 @@ import (
sdk "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/corehandlers"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol/query"
"github.com/aws/aws-sdk-go/service/cloudwatch"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elasticache"
@@ -186,19 +182,6 @@ func (client *SAwsClient) GetAccountId() string {
return client.ownerId
}
/*
func (self *SAwsClient) UpdateAccount(accessKey, secret string) error {
if self.accessKey != accessKey || self.accessSecret != secret {
self.accessKey = accessKey
self.accessSecret = secret
self.iregions = nil
return self.fetchRegions()
} else {
return nil
}
}
*/
var (
// cache for describeRegions
describeRegionResult map[string]*ec2.DescribeRegionsOutput = map[string]*ec2.DescribeRegionsOutput{}
@@ -328,26 +311,6 @@ func (client *SAwsClient) fetchOwnerId() error {
return errors.Wrap(err, "GetCallerIdentity")
}
client.ownerId = ident.Account
/* s, err := client.getDefaultSession()
if err != nil {
return errors.Wrap(err, "getDefaultSession")
}
s3cli := s3.New(s)
output, err := s3cli.ListBuckets(&s3.ListBucketsInput{})
if err != nil {
return errors.Wrap(err, "ListBuckets")
}
if output.Owner != nil {
if output.Owner.ID != nil {
client.ownerId = *output.Owner.ID
}
if output.Owner.DisplayName != nil {
client.ownerName = *output.Owner.DisplayName
}
} */
return nil
}
@@ -527,40 +490,6 @@ func (self *SAwsClient) GetAccessEnv() string {
}
}
func (self *SAwsClient) request(regionId, serviceName, serviceId, apiVersion string, apiName string, params map[string]string, retval interface{}, assumeRole bool) error {
if len(regionId) == 0 {
regionId = self.getDefaultRegionId()
}
session, err := self.getAwsSession(regionId, assumeRole)
if err != nil {
return err
}
c := session.ClientConfig(serviceName)
metadata := metadata.ClientInfo{
ServiceName: serviceName,
ServiceID: serviceId,
SigningName: c.SigningName,
SigningRegion: c.SigningRegion,
Endpoint: c.Endpoint,
APIVersion: apiVersion,
}
if self.debug {
logLevel := aws.LogLevelType(uint(aws.LogDebugWithRequestErrors) + uint(aws.LogDebugWithHTTPBody))
c.Config.LogLevel = &logLevel
}
client := client.New(*c.Config, metadata, c.Handlers)
client.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
client.Handlers.Build.PushBackNamed(buildHandler)
client.Handlers.Unmarshal.PushBackNamed(UnmarshalHandler)
client.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
client.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
client.Handlers.Validate.Remove(corehandlers.ValidateEndpointHandler)
return jsonRequest(client, apiName, params, retval, true)
}
func (self *SAwsClient) iamRequest(apiName string, params map[string]string, retval interface{}) error {
return self.request("", IAM_SERVICE_NAME, IAM_SERVICE_ID, "2010-05-08", apiName, params, retval, true)
}
@@ -569,30 +498,6 @@ func (self *SAwsClient) stsRequest(apiName string, params map[string]string, ret
return self.request("", STS_SERVICE_NAME, STS_SERVICE_ID, "2011-06-15", apiName, params, retval, false)
}
func jsonRequest(cli *client.Client, apiName string, params map[string]string, retval interface{}, debug bool) error {
op := &request.Operation{
Name: apiName,
HTTPMethod: "POST",
HTTPPath: "/",
Paginator: &request.Paginator{
InputTokens: []string{"NextToken"},
OutputTokens: []string{"NextToken"},
LimitToken: "MaxResults",
TruncationToken: "",
},
}
req := cli.NewRequest(op, params, retval)
err := req.Send()
if err != nil {
if e, ok := err.(awserr.RequestFailure); ok && e.StatusCode() == 404 {
return cloudprovider.ErrNotFound
}
return err
}
return nil
}
func (self *SAwsClient) GetCapabilities() []string {
caps := []string{
// cloudprovider.CLOUD_CAPABILITY_PROJECT,
+233
View File
@@ -0,0 +1,233 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 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 aws
import (
"encoding/xml"
"io"
"io/ioutil"
"net/url"
"strings"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/corehandlers"
"github.com/aws/aws-sdk-go/aws/request"
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol/query"
"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
var UnmarshalHandler = request.NamedHandler{Name: "yunion.query.Unmarshal", Fn: Unmarshal}
func Unmarshal(r *request.Request) {
defer r.HTTPResponse.Body.Close()
if r.DataFilled() {
var decoder *xml.Decoder
if DEBUG {
body, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("ioutil.ReadAll", "read response body", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
log.Debugf("response: \n%s", string(body))
decoder = xml.NewDecoder(strings.NewReader(string(body)))
} else {
decoder = xml.NewDecoder(r.HTTPResponse.Body)
}
if r.ClientInfo.ServiceID == EC2_SERVICE_ID {
err := decoder.Decode(r.Data)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("SerializationError", "failed decoding EC2 Query response", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
}
return
}
for {
tok, err := decoder.Token()
if err != nil {
if err == io.EOF {
break
}
r.Error = awserr.NewRequestFailure(
awserr.New("decoder.Token()", "get token", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
if tok == nil {
break
}
switch typed := tok.(type) {
case xml.CharData:
continue
case xml.StartElement:
if typed.Name.Local == r.Operation.Name+"Result" {
err = decoder.DecodeElement(r.Data, &typed)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("DecodeElement", "failed decoding Query response", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
}
return
}
case xml.EndElement:
break
}
}
}
}
var buildHandler = request.NamedHandler{Name: "yunion.query.Build", Fn: Build}
func Build(r *request.Request) {
body := url.Values{
"Action": {r.Operation.Name},
"Version": {r.ClientInfo.APIVersion},
}
if r.Params != nil {
if params, ok := r.Params.(map[string]string); ok {
for k, v := range params {
body.Add(k, v)
}
}
}
if DEBUG {
log.Debugf("params: %s", body.Encode())
}
if !r.IsPresigned() {
r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode()))
} else { // This is a pre-signed request
r.HTTPRequest.Method = "GET"
r.HTTPRequest.URL.RawQuery = body.Encode()
}
}
var UnmarshalErrorHandler = request.NamedHandler{Name: "awssdk.ec2query.UnmarshalError", Fn: UnmarshalError}
func UnmarshalError(r *request.Request) {
defer r.HTTPResponse.Body.Close()
respErr := &struct {
XMLName xml.Name `xml:"Response"`
Code string `xml:"Errors>Error>Code"`
Message string `xml:"Errors>Error>Message"`
RequestID string `xml:"RequestID"`
}{}
err := xmlutil.UnmarshalXMLError(&respErr, r.HTTPResponse.Body)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New(request.ErrCodeSerialization,
"failed to unmarshal error message", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
if strings.Contains(respErr.Code, "NotFound") {
r.Error = errors.Wrapf(cloudprovider.ErrNotFound, jsonutils.Marshal(respErr).String())
return
}
r.Error = awserr.NewRequestFailure(
awserr.New(respErr.Code, respErr.Message, nil),
r.HTTPResponse.StatusCode,
respErr.RequestID,
)
}
func (self *SAwsClient) request(regionId, serviceName, serviceId, apiVersion string, apiName string, params map[string]string, retval interface{}, assumeRole bool) error {
if len(regionId) == 0 {
regionId = self.getDefaultRegionId()
}
session, err := self.getAwsSession(regionId, assumeRole)
if err != nil {
return err
}
c := session.ClientConfig(serviceName)
metadata := metadata.ClientInfo{
ServiceName: serviceName,
ServiceID: serviceId,
SigningName: c.SigningName,
SigningRegion: c.SigningRegion,
Endpoint: c.Endpoint,
APIVersion: apiVersion,
}
if self.debug {
logLevel := aws.LogLevelType(uint(aws.LogDebugWithRequestErrors) + uint(aws.LogDebugWithHTTPBody))
c.Config.LogLevel = &logLevel
}
client := client.New(*c.Config, metadata, c.Handlers)
client.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
client.Handlers.Build.PushBackNamed(buildHandler)
client.Handlers.Unmarshal.PushBackNamed(UnmarshalHandler)
client.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
client.Handlers.UnmarshalError.PushBackNamed(UnmarshalErrorHandler)
client.Handlers.Validate.Remove(corehandlers.ValidateEndpointHandler)
return jsonRequest(client, apiName, params, retval, true)
}
func jsonRequest(cli *client.Client, apiName string, params map[string]string, retval interface{}, debug bool) error {
op := &request.Operation{
Name: apiName,
HTTPMethod: "POST",
HTTPPath: "/",
Paginator: &request.Paginator{
InputTokens: []string{"NextToken"},
OutputTokens: []string{"NextToken"},
LimitToken: "MaxResults",
TruncationToken: "",
},
}
req := cli.NewRequest(op, params, retval)
err := req.Send()
if err != nil {
if e, ok := err.(awserr.RequestFailure); ok && e.StatusCode() == 404 {
return cloudprovider.ErrNotFound
}
return err
}
return nil
}
+131 -195
View File
@@ -18,10 +18,7 @@ import (
"fmt"
"time"
"github.com/aws/aws-sdk-go/service/ec2"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/apis/billing"
@@ -40,17 +37,19 @@ type SEipAddress struct {
multicloud.SEipBase
multicloud.AwsTags
AllocationId string
Bandwidth int
Status string
InstanceId string
AssociationId string
Domain string
NetworkInterfaceId string
NetworkInterfaceOwnerId string
PrivateIpAddress string
IpAddress string
Name string
AllocationId string `xml:"allocationId"`
AssociationId string `xml:"associationId"`
CarrierIp string `xml:"carrierIp"`
CustomerOwnedIp string `xml:"customerOwnedIp"`
CustomerOwnedIpv4Pool string `xml:"customerOwnedIpv4Pool"`
Domain string `xml:"domain"`
InstanceId string `xml:"instanceId"`
NetworkBorderGroup string `xml:"networkBorderGroup"`
NetworkInterfaceId string `xml:"networkInterfaceId"`
NetworkInterfaceOwnerId string `xml:"networkInterfaceOwnerId"`
PrivateIpAddress string `xml:"privateIpAddress"`
PublicIp string `xml:"publicIp"`
PublicIpv4Pool string `xml:"publicIpv4Pool"`
}
func (self *SEipAddress) GetId() string {
@@ -58,11 +57,11 @@ func (self *SEipAddress) GetId() string {
}
func (self *SEipAddress) GetName() string {
if len(self.Name) == 0 {
return self.IpAddress
name := self.AwsTags.GetName()
if len(name) > 0 {
return name
}
return self.Name
return self.AllocationId
}
func (self *SEipAddress) GetGlobalId() string {
@@ -70,13 +69,7 @@ func (self *SEipAddress) GetGlobalId() string {
}
func (self *SEipAddress) GetStatus() string {
switch self.Status {
// todo: EIP_STATUS_INUSE 对应READY
case EIP_STATUS_AVAILABLE, EIP_STATUS_INUSE:
return api.EIP_STATUS_READY
default:
return api.EIP_STATUS_UNKNOWN
}
return api.EIP_STATUS_READY
}
func (self *SEipAddress) Refresh() error {
@@ -94,33 +87,67 @@ func (self *SEipAddress) IsEmulated() bool {
if self.AllocationId == self.InstanceId {
return true
}
return false
}
func (self *SEipAddress) GetIpAddr() string {
return self.IpAddress
return self.PublicIp
}
func (self *SEipAddress) GetMode() string {
if self.InstanceId == self.AllocationId {
return api.EIP_MODE_INSTANCE_PUBLICIP
} else {
return api.EIP_MODE_STANDALONE_EIP
}
return api.EIP_MODE_STANDALONE_EIP
}
func (self *SEipAddress) GetAssociationType() string {
// todo : ?
if len(self.InstanceId) > 0 {
return api.EIP_ASSOCIATE_TYPE_SERVER
}
if len(self.NetworkInterfaceId) > 0 {
net, err := self.region.GetNetworkInterface(self.NetworkInterfaceId)
if err != nil {
return ""
}
switch net.InterfaceType {
case "nat_gateway":
return api.EIP_ASSOCIATE_TYPE_NAT_GATEWAY
}
}
return api.EIP_ASSOCIATE_TYPE_SERVER
}
func (self *SEipAddress) GetAssociationExternalId() string {
if len(self.InstanceId) > 0 {
return self.InstanceId
}
if len(self.NetworkInterfaceId) > 0 {
net, err := self.region.GetNetworkInterface(self.NetworkInterfaceId)
if err != nil {
return ""
}
switch net.InterfaceType {
case "nat_gateway":
nats, err := self.region.GetNatGateways(nil, net.VpcId, net.SubnetId)
if err != nil {
return ""
}
for i := range nats {
for _, addr := range nats[i].NatGatewayAddresses {
if addr.PublicIp == self.PublicIp {
return nats[i].GetGlobalId()
}
}
}
return ""
}
}
return self.InstanceId
}
func (self *SEipAddress) GetBandwidth() int {
return self.Bandwidth
return 0
}
func (self *SEipAddress) GetINetworkId() string {
@@ -128,7 +155,6 @@ func (self *SEipAddress) GetINetworkId() string {
}
func (self *SEipAddress) GetInternetChargeType() string {
// todo : implement me
return api.EIP_CHARGE_TYPE_BY_TRAFFIC
}
@@ -137,207 +163,117 @@ func (self *SEipAddress) Delete() error {
}
func (self *SEipAddress) Associate(conf *cloudprovider.AssociateConfig) error {
err := self.region.AssociateEip(self.AllocationId, conf.InstanceId)
if err != nil {
return err
}
err = cloudprovider.WaitStatusWithDelay(self, api.EIP_STATUS_READY, 5*time.Second, 10*time.Second, 180*time.Second)
return err
return self.region.AssociateEip(self.AllocationId, conf.InstanceId)
}
func (self *SEipAddress) Dissociate() error {
err := self.region.DissociateEip(self.AllocationId, self.InstanceId)
if err != nil {
return err
if len(self.InstanceId) > 0 {
return self.region.DissociateEip(self.InstanceId)
}
err = cloudprovider.WaitStatus(self, api.EIP_STATUS_READY, 10*time.Second, 180*time.Second)
return err
return self.region.DissociateEip(self.AssociationId)
}
func (self *SEipAddress) ChangeBandwidth(bw int) error {
return self.region.UpdateEipBandwidth(self.AllocationId, bw)
}
func (self *SRegion) GetEips(eipId string, eipAddress string, offset int, limit int) ([]SEipAddress, int, error) {
params := ec2.DescribeAddressesInput{}
if len(eipId) > 0 {
params.SetAllocationIds([]*string{&eipId})
func (self *SRegion) GetEips(id, ip, associateId string) ([]SEipAddress, error) {
params := map[string]string{}
if len(id) > 0 {
params["AllocationId.1"] = id
}
if len(eipAddress) > 0 {
params.SetPublicIps([]*string{&eipAddress})
if len(ip) > 0 {
params["PublicIp.1"] = ip
}
ec2Client, err := self.getEc2Client()
idx := 1
if len(associateId) > 0 {
params[fmt.Sprintf("Filter.%d.Name", idx)] = "association-id"
params[fmt.Sprintf("Filter.%d.Value.1", idx)] = associateId
idx++
}
result := struct {
AddressesSet []SEipAddress `xml:"addressesSet>item"`
}{}
err := self.ec2Request("DescribeAddresses", params, &result)
if err != nil {
return nil, 0, errors.Wrap(err, "getEc2Client")
return nil, errors.Wrapf(err, "DescribeAddresses")
}
res, err := ec2Client.DescribeAddresses(&params)
err = parseNotFoundError(err)
if err != nil {
log.Errorf("DescribeEipAddresses fail %s", err)
return nil, 0, err
}
eips := make([]SEipAddress, 0)
for _, ip := range res.Addresses {
if err := FillZero(ip); err != nil {
return nil, 0, err
}
tagspec := TagSpec{ResourceType: "eip"}
tagspec.LoadingEc2Tags(ip.Tags)
var status string
if len(*ip.AssociationId) > 0 {
status = EIP_STATUS_INUSE
} else {
status = EIP_STATUS_AVAILABLE
}
eip := SEipAddress{
region: self,
AllocationId: *ip.AllocationId,
Status: status,
InstanceId: *ip.InstanceId,
AssociationId: *ip.AssociationId,
Domain: *ip.Domain,
NetworkInterfaceId: *ip.NetworkInterfaceId,
NetworkInterfaceOwnerId: *ip.NetworkInterfaceOwnerId,
PrivateIpAddress: *ip.PrivateIpAddress,
IpAddress: *ip.PublicIp,
Name: tagspec.GetNameTag(),
}
jsonutils.Update(&eip.AwsTags.TagSet, ip.Tags)
eips = append(eips, eip)
}
return eips, len(eips), nil
return result.AddressesSet, nil
}
func (self *SRegion) GetEip(eipId string) (*SEipAddress, error) {
// 这里必须强制要求eipId大于零。避免用户账号正好只有一个eip的情况,返回错误的eip。
if len(eipId) == 0 {
return nil, fmt.Errorf("GetEip eipId should not be emtpy.")
}
eips, total, err := self.GetEips(eipId, "", 0, 0)
func (self *SRegion) GetEip(id string) (*SEipAddress, error) {
eips, err := self.GetEips(id, "", "")
if err != nil {
log.Errorf("GetEips %s: %s", eipId, err)
return nil, errors.Wrap(err, "GetEips")
return nil, errors.Wrapf(err, "GetEips")
}
if total != 1 {
return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetEips")
for i := range eips {
if eips[i].GetGlobalId() == id {
eips[i].region = self
return &eips[i], nil
}
}
return &eips[0], nil
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
}
func (self *SRegion) GetEipByIpAddress(eipAddress string) (*SEipAddress, error) {
eips, total, err := self.GetEips("", eipAddress, 0, 0)
eips, err := self.GetEips("", eipAddress, "")
if err != nil {
log.Errorf("GetEips %s: %s", eipAddress, err)
return nil, errors.Wrap(err, "GetEips")
return nil, errors.Wrapf(err, "GetEips")
}
if total != 1 {
return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetEips")
}
return &eips[0], nil
}
func (self *SRegion) AllocateEIP(domainType string) (*SEipAddress, error) {
params := &ec2.AllocateAddressInput{}
params.SetDomain(domainType)
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
eip, err := ec2Client.AllocateAddress(params)
if err != nil {
log.Errorf("AllocateEipAddress fail %s", err)
return nil, errors.Wrap(err, "AllocateAddress")
}
err = self.fetchInfrastructure()
if err != nil {
return nil, errors.Wrap(err, "fetchInfrastructure")
}
return self.GetEip(*eip.AllocationId)
}
func (self *SRegion) CreateEIP(eip *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
ec2Client, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
// todo: aws 不支持指定bwMbps, chargeType
log.Debugf("CreateEip: aws not support specific params name/bwMbps/chargeType.")
ieip, err := self.AllocateEIP("vpc")
if err == nil && len(eip.Name) > 0 {
eipId := ieip.GetId()
k := "Name"
nameTag := &ec2.Tag{Key: &k, Value: &eip.Name}
params := &ec2.CreateTagsInput{}
params.SetResources([]*string{&eipId})
params.SetTags([]*ec2.Tag{nameTag})
// name 创建成功与否不影响eip的正常使用
if _, e := ec2Client.CreateTags(params); e != nil {
log.Infof("CreateEIP create name tag failed: %s", e)
for i := range eips {
if eips[i].GetIpAddr() == eipAddress {
eips[i].region = self
return &eips[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, eipAddress)
}
return ieip, err
func (self *SRegion) AllocateEIP(opts *cloudprovider.SEip) (*SEipAddress, error) {
params := map[string]string{
"Domain": "vpc",
}
if len(opts.Name) > 0 {
params["TagSpecification.1.ResourceType"] = "elastic-ip"
params["TagSpecification.1.Tag.1.Key"] = "Name"
params["TagSpecification.1.Tag.1.Value"] = opts.Name
}
ret := SEipAddress{region: self}
err := self.ec2Request("AllocateAddress", params, &ret)
if err != nil {
return nil, errors.Wrapf(err, "AllocateAddress")
}
return &ret, nil
}
func (self *SRegion) CreateEIP(opts *cloudprovider.SEip) (cloudprovider.ICloudEIP, error) {
eip, err := self.AllocateEIP(opts)
if err != nil {
return nil, errors.Wrapf(err, "AllocateEIP")
}
return eip, nil
}
func (self *SRegion) DeallocateEIP(eipId string) error {
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
params := map[string]string{
"AllocationId": eipId,
}
params := &ec2.ReleaseAddressInput{}
params.SetAllocationId(eipId)
_, err = ec2Client.ReleaseAddress(params)
return errors.Wrap(err, "ReleaseAddress")
return self.ec2Request("ReleaseAddress", params, nil)
}
func (self *SRegion) AssociateEip(eipId string, instanceId string) error {
params := &ec2.AssociateAddressInput{}
params.SetAllocationId(eipId)
params.SetInstanceId(instanceId)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
params := map[string]string{
"AllocationId": eipId,
"InstanceId": instanceId,
}
_, err = ec2Client.AssociateAddress(params)
return errors.Wrap(err, "AssociateAddress")
return self.ec2Request("AssociateAddress", params, nil)
}
func (self *SRegion) DissociateEip(eipId string, instanceId string) error {
eip, err := self.GetEip(eipId)
if err != nil {
return err
func (self *SRegion) DissociateEip(insId string) error {
params := map[string]string{
"AssociationId": insId,
}
if len(eip.AssociationId) == 0 {
// 已经是解绑状态
return nil
}
if eip.InstanceId != instanceId {
return fmt.Errorf("eip %s associate with another instance %s", eipId, eip.InstanceId)
}
params := &ec2.DisassociateAddressInput{}
params.SetAssociationId(eip.AssociationId)
ec2Client, err := self.getEc2Client()
if err != nil {
return errors.Wrap(err, "getEc2Client")
}
_, err = ec2Client.DisassociateAddress(params)
return errors.Wrap(err, "DisassociateAddress")
return self.ec2Request("DisassociateAddress", params, nil)
}
func (self *SRegion) UpdateEipBandwidth(eipId string, bw int) error {
+13 -15
View File
@@ -90,7 +90,7 @@ type SInstance struct {
VlanId string // subnet ID ?
VpcAttributes SVpcAttributes
SecurityGroupIds SSecurityGroupIds
NetworkInterfaces SNetworkInterfaces
NetworkInterfaces []SNetworkInterface
EipAddress SEipAddress
Disks []string
DeviceNames []string
@@ -262,7 +262,7 @@ func (self *SInstance) GetIDisks() ([]cloudprovider.ICloudDisk, error) {
func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
var (
networkInterfaces = self.NetworkInterfaces.NetworkInterface
networkInterfaces = self.NetworkInterfaces
nics = make([]cloudprovider.ICloudNic, 0)
)
for _, networkInterface := range networkInterfaces {
@@ -278,20 +278,18 @@ func (self *SInstance) GetINics() ([]cloudprovider.ICloudNic, error) {
}
func (self *SInstance) GetIEIP() (cloudprovider.ICloudEIP, error) {
if len(self.EipAddress.IpAddress) > 0 {
return self.host.zone.region.GetEipByIpAddress(self.EipAddress.IpAddress)
} else if len(self.PublicIpAddress.IpAddress) > 0 {
eip := SEipAddress{}
if len(self.EipAddress.PublicIp) > 0 {
return self.host.zone.region.GetEipByIpAddress(self.EipAddress.PublicIp)
}
if len(self.PublicIpAddress.IpAddress) > 0 {
eip := SEipAddress{region: self.host.zone.region}
eip.region = self.host.zone.region
eip.IpAddress = self.PublicIpAddress.IpAddress[0]
eip.PublicIp = self.PublicIpAddress.IpAddress[0]
eip.InstanceId = self.InstanceId
eip.AllocationId = self.InstanceId // fixed. AllocationId等于InstanceId即表示为 仿真EIP。
eip.Bandwidth = 10000
eip.Status = EIP_STATUS_INUSE
return &eip, nil
} else {
return nil, nil
}
return nil, nil
}
func (self *SInstance) GetVcpuCount() int {
@@ -618,7 +616,7 @@ func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit
}
}
var networkInterfaces SNetworkInterfaces
networkInterfaces := []SNetworkInterface{}
eipAddress := SEipAddress{}
for _, n := range instance.NetworkInterfaces {
i := SNetworkInterface{
@@ -626,12 +624,12 @@ func (self *SRegion) GetInstances(zoneId string, ids []string, offset int, limit
NetworkInterfaceId: *n.NetworkInterfaceId,
PrivateIpAddress: *n.PrivateIpAddress,
}
networkInterfaces.NetworkInterface = append(networkInterfaces.NetworkInterface, i)
networkInterfaces = append(networkInterfaces, i)
// todo: 可能有多个EIP的情况。目前只支持一个EIP
if n.Association != nil && StrVal(n.Association.IpOwnerId) != "amazon" {
if eipAddress.IpAddress == "" && len(StrVal(n.Association.PublicIp)) > 0 {
eipAddress.IpAddress = *n.Association.PublicIp
if eipAddress.PublicIp == "" && len(StrVal(n.Association.PublicIp)) > 0 {
eipAddress.PublicIp = *n.Association.PublicIp
}
}
}
+244
View File
@@ -0,0 +1,244 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 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 aws
import (
"fmt"
"strings"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud"
)
type NatGatewayAddress struct {
AllocationId string `xml:"allocationId"`
NetworkInterfaceId string `xml:"networkInterfaceId"`
PrivateIp string `xml:"privateIp"`
PublicIp string `xml:"publicIp"`
}
type ProvisionedBandwidth struct {
ProvisionTime time.Time `xml:"provisionTime"`
Provisioned string `xml:"provisioned"`
RequestTime time.Time `xml:"requestTime"`
Requested string `xml:"requested"`
Status string `xml:"status"`
}
type SNatGateway struct {
multicloud.SNatGatewayBase
multicloud.AwsTags
region *SRegion
ConnectivityType string `xml:"connectivityType"`
CreateTime time.Time `xml:"createTime"`
DeleteTime time.Time `xml:"deleteTime"`
FailureCode string `xml:"failureCode"`
FailureMessage string `xml:"failureMessage"`
NatGatewayAddresses []NatGatewayAddress `xml:"natGatewayAddressSet>item"`
NatGatewayId string `xml:"natGatewayId"`
ProvisionedBandwidth ProvisionedBandwidth `xml:"provisionedBandwidth"`
// pending | failed | available | deleting | deleted
State string `xml:"state"`
SubnetId string `xml:"subnetId"`
VpcId string `xml:"vpcId"`
}
func (self *SNatGateway) GetName() string {
name := self.AwsTags.GetName()
if len(name) > 0 {
return name
}
return self.NatGatewayId
}
func (self *SNatGateway) GetId() string {
return self.NatGatewayId
}
func (self *SNatGateway) GetGlobalId() string {
return self.NatGatewayId
}
func (self *SNatGateway) GetStatus() string {
switch self.State {
case "pending":
return api.NAT_STATUS_ALLOCATE
case "failed":
return api.NAT_STATUS_CREATE_FAILED
case "available":
return api.NAT_STAUTS_AVAILABLE
case "deleting", "deleted":
return api.NAT_STATUS_DELETING
default:
return api.NAT_STATUS_UNKNOWN
}
}
func (self *SNatGateway) GetNatSpec() string {
return ""
}
func (self *SNatGateway) Refresh() error {
nat, err := self.region.GetNatGateway(self.NatGatewayId)
if err != nil {
return err
}
return jsonutils.Update(self, nat)
}
func (self *SNatGateway) GetIEips() ([]cloudprovider.ICloudEIP, error) {
eips, err := self.region.GetEips("", "", self.NatGatewayId)
if err != nil {
return nil, errors.Wrapf(err, "GetEIPs")
}
ret := []cloudprovider.ICloudEIP{}
for i := range eips {
eips[i].region = self.region
ret = append(ret, &eips[i])
}
return ret, nil
}
func (self *SNatGateway) GetINatDTable() ([]cloudprovider.ICloudNatDEntry, error) {
return []cloudprovider.ICloudNatDEntry{}, nil
}
func (self *SNatGateway) GetINatSTable() ([]cloudprovider.ICloudNatSEntry, error) {
return []cloudprovider.ICloudNatSEntry{}, nil
}
func (self *SNatGateway) GetINatDEntryByID(id string) (cloudprovider.ICloudNatDEntry, error) {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
}
func (self *SNatGateway) GetINatSEntryByID(id string) (cloudprovider.ICloudNatSEntry, error) {
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
}
func (self *SNatGateway) CreateINatDEntry(rule cloudprovider.SNatDRule) (cloudprovider.ICloudNatDEntry, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SNatGateway) CreateINatSEntry(rule cloudprovider.SNatSRule) (cloudprovider.ICloudNatSEntry, error) {
return nil, cloudprovider.ErrNotImplemented
}
func (self *SNatGateway) GetINetworkId() string {
return self.SubnetId
}
func (self *SNatGateway) GetBandwidthMb() int {
return 0
}
func (self *SNatGateway) GetIpAddr() string {
ipAddrs := []string{}
for _, addr := range self.NatGatewayAddresses {
if len(addr.PrivateIp) > 0 {
ipAddrs = append(ipAddrs, addr.PrivateIp)
}
}
return strings.Join(ipAddrs, ",")
}
func (self *SNatGateway) Delete() error {
return self.region.DeleteNatgateway(self.NatGatewayId)
}
func (self *SRegion) DeleteNatgateway(id string) error {
params := map[string]string{
"NatGatewayId": id,
}
return self.ec2Request("DeleteNatGateway", params, nil)
}
func (self *SRegion) GetNatGateways(ids []string, vpcId, subnetId string) ([]SNatGateway, error) {
params := map[string]string{}
for i, id := range ids {
params[fmt.Sprintf("NatGatewayId.%d", i+1)] = id
}
idx := 1
if len(vpcId) > 0 {
params[fmt.Sprintf("Filter.%d.Name", idx)] = "vpc-id"
params[fmt.Sprintf("Filter.%d.Value.1", idx)] = vpcId
idx++
}
if len(subnetId) > 0 {
params[fmt.Sprintf("Filter.%d.Name", idx)] = "subnet-id"
params[fmt.Sprintf("Filter.%d.Value.1", idx)] = subnetId
idx++
}
params[fmt.Sprintf("Filter.%d.Name", idx)] = "state"
for i, state := range []string{
"pending",
"failed",
"available",
"deleting",
} {
params[fmt.Sprintf("Filter.%d.Value.%d", idx, i+1)] = state
}
idx++
ret := []SNatGateway{}
for {
result := struct {
Nats []SNatGateway `xml:"natGatewaySet>item"`
NextToken string `xml:"nextToken"`
}{}
err := self.ec2Request("DescribeNatGateways", params, &result)
if err != nil {
return nil, errors.Wrapf(err, "DescribeNatGateways")
}
ret = append(ret, result.Nats...)
if len(result.NextToken) == 0 || len(result.Nats) == 0 {
break
}
params["NextToken"] = result.NextToken
}
return ret, nil
}
func (self *SRegion) GetNatGateway(id string) (*SNatGateway, error) {
nats, err := self.GetNatGateways([]string{id}, "", "")
if err != nil {
return nil, errors.Wrapf(err, "GetNatGateways")
}
for i := range nats {
if nats[i].GetGlobalId() == id {
nats[i].region = self
return &nats[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
}
func (self *SVpc) GetINatGateways() ([]cloudprovider.ICloudNatGateway, error) {
nats, err := self.region.GetNatGateways(nil, self.VpcId, "")
if err != nil {
return nil, errors.Wrapf(err, "GetINatGateways")
}
ret := []cloudprovider.ICloudNatGateway{}
for i := range nats {
nats[i].region = self.region
ret = append(ret, &nats[i])
}
return ret, nil
}
+33 -8
View File
@@ -18,6 +18,8 @@ import (
"time"
"yunion.io/x/pkg/errors"
"yunion.io/x/onecloud/pkg/cloudprovider"
)
type SGroupSet struct {
@@ -60,16 +62,39 @@ type SNetworkInterface struct {
InterfaceType string `xml:"interfaceType"`
}
type SNetworkInterfaces struct {
NetworkInterface []SNetworkInterface `xml:"networkInterfaceSet>item"`
func (self *SRegion) GetNetworkInterface(id string) (*SNetworkInterface, error) {
nets, err := self.GetNetworkInterfaces(id)
if err != nil {
return nil, errors.Wrapf(err, "GetNetworkInterface")
}
for i := range nets {
if nets[i].NetworkInterfaceId == id {
return &nets[i], nil
}
}
return nil, errors.Wrapf(cloudprovider.ErrNotFound, id)
}
func (region *SRegion) GetNetworkInterfaces() ([]SNetworkInterface, error) {
func (self *SRegion) GetNetworkInterfaces(id string) ([]SNetworkInterface, error) {
params := map[string]string{}
interfaces := SNetworkInterfaces{}
err := region.ec2Request("DescribeNetworkInterfaces", params, &interfaces)
if err != nil {
return nil, errors.Wrap(err, "DescribeNetworkInterfaces")
if len(id) > 0 {
params["NetworkInterfaceId.1"] = id
}
return interfaces.NetworkInterface, nil
ret := []SNetworkInterface{}
for {
result := struct {
NetworkInterfaceSet []SNetworkInterface `xml:"networkInterfaceSet>item"`
NextToken string `xml:"nextToken"`
}{}
err := self.ec2Request("DescribeNetworkInterfaces", params, &result)
if err != nil {
return nil, errors.Wrap(err, "DescribeNetworkInterfaces")
}
ret = append(ret, result.NetworkInterfaceSet...)
if len(result.NextToken) == 0 || len(result.NetworkInterfaceSet) == 0 {
break
}
params["NextToken"] = result.NextToken
}
return ret, nil
}
+9 -129
View File
@@ -15,19 +15,13 @@
package aws
import (
"encoding/xml"
"fmt"
"io"
"io/ioutil"
"net/url"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/client"
"github.com/aws/aws-sdk-go/aws/client/metadata"
"github.com/aws/aws-sdk-go/aws/request"
"github.com/aws/aws-sdk-go/aws/session"
v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
"github.com/aws/aws-sdk-go/private/protocol/query"
@@ -235,108 +229,6 @@ func (self *SRegion) getResourceGroupTagClient() (*resourcegroupstaggingapi.Reso
return self.resourceGroupTagClient, nil
}
var UnmarshalHandler = request.NamedHandler{Name: "yunion.query.Unmarshal", Fn: Unmarshal}
func Unmarshal(r *request.Request) {
defer r.HTTPResponse.Body.Close()
if r.DataFilled() {
var decoder *xml.Decoder
if DEBUG {
body, err := ioutil.ReadAll(r.HTTPResponse.Body)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("ioutil.ReadAll", "read response body", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
log.Debugf("response: \n%s", string(body))
decoder = xml.NewDecoder(strings.NewReader(string(body)))
} else {
decoder = xml.NewDecoder(r.HTTPResponse.Body)
}
if r.ClientInfo.ServiceID == EC2_SERVICE_ID {
err := decoder.Decode(r.Data)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("SerializationError", "failed decoding EC2 Query response", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
}
return
}
for {
tok, err := decoder.Token()
if err != nil {
if err == io.EOF {
break
}
r.Error = awserr.NewRequestFailure(
awserr.New("decoder.Token()", "get token", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
return
}
if tok == nil {
break
}
switch typed := tok.(type) {
case xml.CharData:
continue
case xml.StartElement:
if typed.Name.Local == r.Operation.Name+"Result" {
err = decoder.DecodeElement(r.Data, &typed)
if err != nil {
r.Error = awserr.NewRequestFailure(
awserr.New("DecodeElement", "failed decoding Query response", err),
r.HTTPResponse.StatusCode,
r.RequestID,
)
}
return
}
case xml.EndElement:
break
}
}
}
}
var buildHandler = request.NamedHandler{Name: "yunion.query.Build", Fn: Build}
func Build(r *request.Request) {
body := url.Values{
"Action": {r.Operation.Name},
"Version": {r.ClientInfo.APIVersion},
}
if r.Params != nil {
if params, ok := r.Params.(map[string]string); ok {
for k, v := range params {
body.Add(k, v)
}
}
}
if DEBUG {
log.Debugf("params: %s", body.Encode())
}
if !r.IsPresigned() {
r.HTTPRequest.Method = "POST"
r.HTTPRequest.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=utf-8")
r.SetBufferBody([]byte(body.Encode()))
} else { // This is a pre-signed request
r.HTTPRequest.Method = "GET"
r.HTTPRequest.URL.RawQuery = body.Encode()
}
}
func (self *SRegion) rdsRequest(apiName string, params map[string]string, retval interface{}) error {
return self.client.request(self.RegionId, RDS_SERVICE_NAME, RDS_SERVICE_ID, "2014-10-31", apiName, params, retval, true)
}
@@ -553,19 +445,14 @@ func (self *SRegion) GetIDiskById(id string) (cloudprovider.ICloudDisk, error) {
}
func (self *SRegion) GetIEips() ([]cloudprovider.ICloudEIP, error) {
_, err := self.getEc2Client()
if err != nil {
return nil, errors.Wrap(err, "getEc2Client")
}
eips, total, err := self.GetEips("", "", 0, 0)
eips, err := self.GetEips("", "", "")
if err != nil {
return nil, errors.Wrap(err, "GetEips")
}
ret := make([]cloudprovider.ICloudEIP, total)
for i := 0; i < len(eips); i += 1 {
ret[i] = &eips[i]
ret := []cloudprovider.ICloudEIP{}
for i := range eips {
eips[i].region = self
ret = append(ret, &eips[i])
}
return ret, nil
}
@@ -732,19 +619,12 @@ func (self *SRegion) CreateIVpc(opts *cloudprovider.VpcCreateOptions) (cloudprov
return self.GetIVpcById(*vpc.Vpc.VpcId)
}
func (self *SRegion) GetIEipById(eipId string) (cloudprovider.ICloudEIP, error) {
eips, total, err := self.GetEips(eipId, "", 0, 0)
func (self *SRegion) GetIEipById(id string) (cloudprovider.ICloudEIP, error) {
eip, err := self.GetEip(id)
if err != nil {
log.Errorf("GetEips %s: %s", eipId, err)
return nil, errors.Wrap(err, "GetEips")
return nil, errors.Wrap(err, "GetEip")
}
if total == 0 {
return nil, errors.Wrap(cloudprovider.ErrNotFound, "GetIEipById")
}
if total > 1 {
return nil, cloudprovider.ErrDuplicateId
}
return &eips[0], nil
return eip, nil
}
func (self *SRegion) GetProvider() string {
+18 -9
View File
@@ -15,28 +15,32 @@
package shell
import (
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/multicloud/aws"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type EipListOptions struct {
Offset int `help:"List offset"`
Limit int `help:"List limit"`
Id string
Addr string
AssociateId string
}
shellutils.R(&EipListOptions{}, "eip-list", "List eips", func(cli *aws.SRegion, args *EipListOptions) error {
eips, total, e := cli.GetEips("", "", args.Offset, args.Limit)
if e != nil {
return e
eips, err := cli.GetEips(args.Id, args.Addr, args.AssociateId)
if err != nil {
return err
}
printList(eips, total, args.Offset, args.Limit, []string{})
printList(eips, 0, 0, 0, []string{})
return nil
})
type EipAllocateOptions struct {
Name string
}
shellutils.R(&EipAllocateOptions{}, "eip-create", "Allocate an EIP", func(cli *aws.SRegion, args *EipAllocateOptions) error {
eip, err := cli.AllocateEIP("vpc")
opts := cloudprovider.SEip{Name: args.Name}
eip, err := cli.AllocateEIP(&opts)
if err != nil {
return err
}
@@ -60,8 +64,13 @@ func init() {
err := cli.AssociateEip(args.ID, args.INSTANCE)
return err
})
shellutils.R(&EipAssociateOptions{}, "eip-dissociate", "Dissociate an EIP", func(cli *aws.SRegion, args *EipAssociateOptions) error {
err := cli.DissociateEip(args.ID, args.INSTANCE)
type EipDissociateOptions struct {
INSTANCE string `help:"Instance ID"`
}
shellutils.R(&EipDissociateOptions{}, "eip-dissociate", "Dissociate an EIP", func(cli *aws.SRegion, args *EipDissociateOptions) error {
err := cli.DissociateEip(args.INSTANCE)
return err
})
}
+45
View File
@@ -0,0 +1,45 @@
// Copyright 2019 Yunion
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// 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 shell
import (
"yunion.io/x/onecloud/pkg/multicloud/aws"
"yunion.io/x/onecloud/pkg/util/shellutils"
)
func init() {
type NatListOptions struct {
Ids []string
VpcId string
SubnetId string
}
shellutils.R(&NatListOptions{}, "natgateway-list", "List natgateway", func(cli *aws.SRegion, args *NatListOptions) error {
nats, err := cli.GetNatGateways(args.Ids, args.VpcId, args.SubnetId)
if err != nil {
return err
}
printList(nats, 0, 0, 0, nil)
return nil
})
type NatIdOptions struct {
ID string
}
shellutils.R(&NatIdOptions{}, "natgateway-delete", "Delete natgateway", func(cli *aws.SRegion, args *NatIdOptions) error {
return cli.DeleteNatgateway(args.ID)
})
}
+2 -1
View File
@@ -21,9 +21,10 @@ import (
func init() {
type NetworkInterfaceListOptions struct {
Id string
}
shellutils.R(&NetworkInterfaceListOptions{}, "network-interface-list", "List network interfaces", func(cli *aws.SRegion, args *NetworkInterfaceListOptions) error {
interfaces, err := cli.GetNetworkInterfaces()
interfaces, err := cli.GetNetworkInterfaces(args.Id)
if err != nil {
return err
}
+1 -1
View File
@@ -598,7 +598,7 @@ func (self *SRegion) assignSecurityGroups(secgroupIds []*string, instanceId stri
return errors.Wrap(err, "getEc2Client")
}
for _, eth := range instance.NetworkInterfaces.NetworkInterface {
for _, eth := range instance.NetworkInterfaces {
params := &ec2.ModifyNetworkInterfaceAttributeInput{}
params.SetNetworkInterfaceId(eth.NetworkInterfaceId)
params.SetGroups(secgroupIds)
+15 -1
View File
@@ -221,8 +221,22 @@ func (self *AzureTags) SetTags(tags map[string]string, replace bool) error {
return errors.Wrap(cloudprovider.ErrNotImplemented, "SetTags")
}
type SAwsTag struct {
Key string `xml:"key"`
Value string `xml:"value"`
}
type AwsTags struct {
TagSet []STag
TagSet []SAwsTag `xml:"tagSet>item"`
}
func (self AwsTags) GetName() string {
for _, tag := range self.TagSet {
if strings.ToLower(tag.Key) == "name" {
return tag.Value
}
}
return ""
}
func (self *AwsTags) GetTags() (map[string]string, error) {