add natGateways tasks for ALICloud

This commit is contained in:
Lily 2019-01-26 14:43:04 +08:00
parent ae6cda7bb1
commit dafbc17c5a
13 changed files with 908 additions and 0 deletions

View File

@ -49,6 +49,33 @@ func (c *ALIModelContext) GetNameForVSwitch(subnetName string) string {
return subnetName + "." + c.ClusterName() return subnetName + "." + c.ClusterName()
} }
// LinkToNateGateway returns the NatGateway object the cluster is located in
func (c *ALIModelContext) LinkToNatGateway() *alitasks.NatGateway {
return &alitasks.NatGateway{Name: s(c.GetNameForNatGateway())}
}
func (c *ALIModelContext) GetNameForNatGateway() string {
return c.ClusterName()
}
// LinkToEIP returns the EIP object the NateGatway is associated to
func (c *ALIModelContext) LinkToEIP() *alitasks.EIP {
return &alitasks.EIP{Name: s(c.GetNameForEIP())}
}
func (c *ALIModelContext) GetNameForEIP() string {
return c.ClusterName()
}
// LinkToVSwitchSNAT returns the VSwitchSNAT object the cluster is located in
func (c *ALIModelContext) LinkToVSwitchSNAT(subnetName string) *alitasks.VSwitch {
return &alitasks.VSwitch{Name: s(c.GetNameForVSwitch(subnetName))}
}
func (c *ALIModelContext) GetNameForVSwitchSNAT(subnetName string) string {
return subnetName + "." + c.ClusterName()
}
// LinkLoadBalancer returns the LoadBalancer object the cluster is located in // LinkLoadBalancer returns the LoadBalancer object the cluster is located in
func (c *ALIModelContext) LinkLoadBalancer() *alitasks.LoadBalancer { func (c *ALIModelContext) LinkLoadBalancer() *alitasks.LoadBalancer {
return &alitasks.LoadBalancer{Name: s(c.GetNameForLoadBalancer())} return &alitasks.LoadBalancer{Name: s(c.GetNameForLoadBalancer())}

View File

@ -50,6 +50,21 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(vpc) c.AddTask(vpc)
} }
natGateway := &alitasks.NatGateway{
Name: s(b.GetNameForNatGateway()),
Lifecycle: b.Lifecycle,
VPC: b.LinkToVPC(),
}
c.AddTask(natGateway)
eip := &alitasks.EIP{
Name: s(b.GetNameForEIP()),
Lifecycle: b.Lifecycle,
NatGateway: b.LinkToNatGateway(),
Available: fi.Bool(false),
}
c.AddTask(eip)
for i := range b.Cluster.Spec.Subnets { for i := range b.Cluster.Spec.Subnets {
subnetSpec := &b.Cluster.Spec.Subnets[i] subnetSpec := &b.Cluster.Spec.Subnets[i]
@ -69,6 +84,20 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
c.AddTask(vswitch) c.AddTask(vswitch)
vswitchSNAT := &alitasks.VSwitchSNAT{
Name: s(b.GetNameForVSwitchSNAT(subnetSpec.Name)),
Lifecycle: b.Lifecycle,
NatGateway: b.LinkToNatGateway(),
VSwitch: b.LinkToVSwitch(subnetSpec.Name),
EIP: b.LinkToEIP(),
}
if subnetSpec.ProviderID != "" {
vswitchSNAT.Shared = fi.Bool(true)
}
c.AddTask(vswitchSNAT)
} }
return nil return nil

View File

@ -48,6 +48,8 @@ const (
typeVolume = "Volume" typeVolume = "Volume"
typeSSHKey = "SSHKey" typeSSHKey = "SSHKey"
typeVPC = "VPC" typeVPC = "VPC"
typeNatGateway = "NatGateway"
typeEIP = "EIP"
) )
type clusterDiscoveryALI struct { type clusterDiscoveryALI struct {
@ -596,6 +598,8 @@ func (d *clusterDiscoveryALI) ListVPC() ([]*resources.Resource, error) {
} }
resourceTrackers = append(resourceTrackers, resourceTracker) resourceTrackers = append(resourceTrackers, resourceTracker)
} }
ListNatGateway(d, vpcsToDelete[0], &resourceTrackers)
} }
return resourceTrackers, nil return resourceTrackers, nil
@ -689,3 +693,138 @@ func DeleteVolume(cloud fi.Cloud, r *resources.Resource) error {
} }
return nil return nil
} }
func ListNatGateway(d *clusterDiscoveryALI, vpcID string, resourceTrackers *[]*resources.Resource) error {
// Delete NateGateway with specified name. All of the EIPs will be deleted.
// We think the NateGateway which owns the designated name is owned.
natGatewaysToDelete := []string{}
eipToDelete := []string{}
name := d.clusterName
pageNumber := 1
pageSize := 50
for {
describeNatGatewaysArgs := &ecs.DescribeNatGatewaysArgs{
RegionId: common.Region(d.aliCloud.Region()),
VpcId: vpcID,
Pagination: common.Pagination{
PageNumber: pageNumber,
PageSize: pageSize,
},
}
natGateways, _, err := d.aliCloud.VpcClient().DescribeNatGateways(describeNatGatewaysArgs)
if err != nil {
return fmt.Errorf("err listing NatGateway:%v", err)
}
if len(natGateways) != 0 {
for _, nateGateway := range natGateways {
natGatewaysToDelete = append(natGatewaysToDelete, nateGateway.NatGatewayId)
for _, ip := range nateGateway.IpLists.IpList {
eipToDelete = append(eipToDelete, ip.AllocationId)
}
}
}
if len(natGateways) < pageSize {
break
} else {
pageNumber++
}
}
if len(natGatewaysToDelete) > 1 {
glog.V(8).Infof("Found multiple natGateways with name %q", name)
} else if len(natGatewaysToDelete) == 1 {
natGatwayTracker := &resources.Resource{
Name: name,
ID: natGatewaysToDelete[0],
Type: typeNatGateway,
Deleter: DeleteNatGateway,
}
*resourceTrackers = append(*resourceTrackers, natGatwayTracker)
natGatwayTracker.Blocks = append(natGatwayTracker.Blocks, typeVPC+":"+vpcID)
for _, eip := range eipToDelete {
resourceTracker := &resources.Resource{
Name: name,
ID: eip,
Type: typeEIP,
Deleter: DeleteEIP,
}
resourceTracker.Blocked = append(resourceTracker.Blocked, typeNatGateway+":"+natGatwayTracker.ID)
*resourceTrackers = append(*resourceTrackers, resourceTracker)
}
}
return nil
}
func DeleteNatGateway(cloud fi.Cloud, r *resources.Resource) error {
c := cloud.(aliup.ALICloud)
describeNatGatewaysArgs := &ecs.DescribeNatGatewaysArgs{
RegionId: common.Region(c.Region()),
NatGatewayId: r.ID,
}
natGateways, _, err := c.VpcClient().DescribeNatGateways(describeNatGatewaysArgs)
if err != nil {
return fmt.Errorf("err listing NatGateway:%v", err)
}
if len(natGateways) > 1 {
glog.V(8).Infof("Found multiple natGateways with ID %q", r.ID)
} else if len(natGateways) == 1 {
for _, snatTableId := range natGateways[0].SnatTableIds.SnatTableId {
describeSnatTableEntriesArgs := &ecs.DescribeSnatTableEntriesArgs{
RegionId: common.Region(c.Region()),
SnatTableId: snatTableId,
}
snatTableEntries, _, err := c.VpcClient().DescribeSnatTableEntries(describeSnatTableEntriesArgs)
if err != nil {
return fmt.Errorf("err Listing snatTableEntries:%v", err)
}
for _, snatTableEntry := range snatTableEntries {
deleteSnatEntryArgs := &ecs.DeleteSnatEntryArgs{
RegionId: common.Region(c.Region()),
SnatTableId: snatTableId,
SnatEntryId: snatTableEntry.SnatEntryId,
}
err := c.VpcClient().DeleteSnatEntry(deleteSnatEntryArgs)
if err != nil {
return fmt.Errorf("err deleting SnatEntryArgs:%v", err)
}
}
}
for _, ip := range natGateways[0].IpLists.IpList {
err := c.VpcClient().UnassociateEipAddress(ip.AllocationId, r.ID)
if err != nil {
return fmt.Errorf("err unassociating EIP:%v", err)
}
}
}
glog.V(2).Infof("Removing NatGateway with Id %s", r.ID)
deleteNatGatewayArgs := &ecs.DeleteNatGatewayArgs{
RegionId: common.Region(c.Region()),
NatGatewayId: r.ID,
}
err = c.EcsClient().DeleteNatGateway(deleteNatGatewayArgs)
if err != nil {
return fmt.Errorf("err deleting NatGateway:%v", err)
}
return nil
}
func DeleteEIP(cloud fi.Cloud, r *resources.Resource) error {
c := cloud.(aliup.ALICloud)
glog.V(2).Infof("Removing EIP with Id %s", r.ID)
err := c.VpcClient().ReleaseEipAddress(r.ID)
if err != nil {
return fmt.Errorf("err deleting EIP:%v", err)
}
return nil
}

View File

@ -11,11 +11,13 @@ go_library(
deps = [ deps = [
"//pkg/apis/kops:go_default_library", "//pkg/apis/kops:go_default_library",
"//pkg/resources:go_default_library", "//pkg/resources:go_default_library",
"//pkg/resources/ali:go_default_library",
"//pkg/resources/aws:go_default_library", "//pkg/resources/aws:go_default_library",
"//pkg/resources/digitalocean:go_default_library", "//pkg/resources/digitalocean:go_default_library",
"//pkg/resources/gce:go_default_library", "//pkg/resources/gce:go_default_library",
"//pkg/resources/openstack:go_default_library", "//pkg/resources/openstack:go_default_library",
"//upup/pkg/fi:go_default_library", "//upup/pkg/fi:go_default_library",
"//upup/pkg/fi/cloudup/aliup:go_default_library",
"//upup/pkg/fi/cloudup/awsup:go_default_library", "//upup/pkg/fi/cloudup/awsup:go_default_library",
"//upup/pkg/fi/cloudup/gce:go_default_library", "//upup/pkg/fi/cloudup/gce:go_default_library",
"//upup/pkg/fi/cloudup/openstack:go_default_library", "//upup/pkg/fi/cloudup/openstack:go_default_library",

View File

@ -21,11 +21,13 @@ import (
"k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/resources" "k8s.io/kops/pkg/resources"
"k8s.io/kops/pkg/resources/ali"
"k8s.io/kops/pkg/resources/aws" "k8s.io/kops/pkg/resources/aws"
"k8s.io/kops/pkg/resources/digitalocean" "k8s.io/kops/pkg/resources/digitalocean"
"k8s.io/kops/pkg/resources/gce" "k8s.io/kops/pkg/resources/gce"
"k8s.io/kops/pkg/resources/openstack" "k8s.io/kops/pkg/resources/openstack"
"k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi"
cloudali "k8s.io/kops/upup/pkg/fi/cloudup/aliup"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup" "k8s.io/kops/upup/pkg/fi/cloudup/awsup"
cloudgce "k8s.io/kops/upup/pkg/fi/cloudup/gce" cloudgce "k8s.io/kops/upup/pkg/fi/cloudup/gce"
cloudopenstack "k8s.io/kops/upup/pkg/fi/cloudup/openstack" cloudopenstack "k8s.io/kops/upup/pkg/fi/cloudup/openstack"
@ -45,6 +47,8 @@ func ListResources(cloud fi.Cloud, clusterName string, region string) (map[strin
return openstack.ListResources(cloud.(cloudopenstack.OpenstackCloud), clusterName) return openstack.ListResources(cloud.(cloudopenstack.OpenstackCloud), clusterName)
case kops.CloudProviderVSphere: case kops.CloudProviderVSphere:
return resources.ListResourcesVSphere(cloud.(*vsphere.VSphereCloud), clusterName) return resources.ListResourcesVSphere(cloud.(*vsphere.VSphereCloud), clusterName)
case kops.CloudProviderALI:
return ali.ListResourcesALI(cloud.(cloudali.ALICloud), clusterName, region)
default: default:
return nil, fmt.Errorf("delete on clusters on %q not (yet) supported", cloud.ProviderID()) return nil, fmt.Errorf("delete on clusters on %q not (yet) supported", cloud.ProviderID())
} }

View File

@ -5,6 +5,8 @@ go_library(
srcs = [ srcs = [
"disk.go", "disk.go",
"disk_fitask.go", "disk_fitask.go",
"eip_fitask.go",
"eip_natgateway_association.go",
"launchconfiguration.go", "launchconfiguration.go",
"launchconfiguration_fitask.go", "launchconfiguration_fitask.go",
"loadbalancer.go", "loadbalancer.go",
@ -13,6 +15,8 @@ go_library(
"loadbalancerlistener_fitask.go", "loadbalancerlistener_fitask.go",
"loadbalancerwhitelist.go", "loadbalancerwhitelist.go",
"loadbalancerwhitelist_fitask.go", "loadbalancerwhitelist_fitask.go",
"natgateway.go",
"natgateway_fitask.go",
"rampolicy.go", "rampolicy.go",
"rampolicy_fitask.go", "rampolicy_fitask.go",
"ramrole.go", "ramrole.go",
@ -28,7 +32,9 @@ go_library(
"vpc.go", "vpc.go",
"vpc_fitask.go", "vpc_fitask.go",
"vswitch.go", "vswitch.go",
"vswitchSNAT.go",
"vswitch_fitask.go", "vswitch_fitask.go",
"vswitchsnat_fitask.go",
], ],
importpath = "k8s.io/kops/upup/pkg/fi/cloudup/alitasks", importpath = "k8s.io/kops/upup/pkg/fi/cloudup/alitasks",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],

View File

@ -0,0 +1,75 @@
/*
Copyright 2018 The Kubernetes Authors.
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.
*/
// Code generated by ""fitask" -type=EIP"; DO NOT EDIT
package alitasks
import (
"encoding/json"
"k8s.io/kops/upup/pkg/fi"
)
// EIP
// JSON marshaling boilerplate
type realEIP EIP
// UnmarshalJSON implements conversion to JSON, supporting an alternate specification of the object as a string
func (o *EIP) UnmarshalJSON(data []byte) error {
var jsonName string
if err := json.Unmarshal(data, &jsonName); err == nil {
o.Name = &jsonName
return nil
}
var r realEIP
if err := json.Unmarshal(data, &r); err != nil {
return err
}
*o = EIP(r)
return nil
}
var _ fi.HasLifecycle = &EIP{}
// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *EIP) GetLifecycle() *fi.Lifecycle {
return o.Lifecycle
}
// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *EIP) SetLifecycle(lifecycle fi.Lifecycle) {
o.Lifecycle = &lifecycle
}
var _ fi.HasName = &EIP{}
// GetName returns the Name of the object, implementing fi.HasName
func (o *EIP) GetName() *string {
return o.Name
}
// SetName sets the Name of the object, implementing fi.SetName
func (o *EIP) SetName(name string) {
o.Name = &name
}
// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *EIP) String() string {
return fi.TaskAsString(o)
}

View File

@ -0,0 +1,165 @@
/*
Copyright 2019 The Kubernetes Authors.
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 alitasks
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/golang/glog"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/aliup"
"k8s.io/kops/upup/pkg/fi/cloudup/terraform"
)
const (
NatType = "Nat"
)
//go:generate fitask -type=EIP
type EIP struct {
Name *string
Lifecycle *fi.Lifecycle
Region *string
ID *string
IpAddress *string
NatGateway *NatGateway
Available *bool
}
var _ fi.CompareWithID = &EIP{}
func (e *EIP) CompareWithID() *string {
return e.Name
}
func (e *EIP) Find(c *fi.Context) (*EIP, error) {
if e.NatGateway == nil || e.NatGateway.ID == nil {
glog.V(4).Infof("NatGateway / NatGatewayId not found for %s, skipping Find", fi.StringValue(e.Name))
return nil, nil
}
cloud := c.Cloud.(aliup.ALICloud)
describeEipAddressesArgs := &ecs.DescribeEipAddressesArgs{
RegionId: common.Region(cloud.Region()),
AssociatedInstanceType: ecs.AssociatedInstanceTypeNat,
AssociatedInstanceId: fi.StringValue(e.NatGateway.ID),
}
eipAddresses, _, err := cloud.VpcClient().DescribeEipAddresses(describeEipAddressesArgs)
if err != nil {
return nil, fmt.Errorf("error finding EIPs: %v", err)
}
// Don't exist EIPs with specified NatGateway.
if len(eipAddresses) == 0 {
return nil, nil
}
if len(eipAddresses) > 1 {
glog.V(4).Infof("The number of specified EIPs with the same NatGatewayId exceeds 1, eipName:%q", *e.Name)
}
glog.V(2).Infof("found matching EIPs: %q", *e.Name)
actual := &EIP{}
actual.IpAddress = fi.String(eipAddresses[0].IpAddress)
actual.ID = fi.String(eipAddresses[0].AllocationId)
actual.Available = fi.Bool(eipAddresses[0].Status == ecs.EipStatusAvailable)
if eipAddresses[0].InstanceId != "" {
actual.NatGateway = &NatGateway{
ID: fi.String(eipAddresses[0].InstanceId),
}
actual.Region = fi.String(cloud.Region())
}
// Ignore "system" fields
actual.Lifecycle = e.Lifecycle
actual.Name = e.Name
e.ID = actual.ID
e.Available = actual.Available
glog.V(4).Infof("found matching EIP %v", actual)
return actual, nil
}
func (e *EIP) Run(c *fi.Context) error {
return fi.DefaultDeltaRunMethod(e, c)
}
func (_ *EIP) CheckChanges(a, e, changes *EIP) error {
return nil
}
func (_ *EIP) RenderALI(t *aliup.ALIAPITarget, a, e, changes *EIP) error {
if a == nil {
glog.V(2).Infof("Creating new EIP for NatGateway:%q", fi.StringValue(e.NatGateway.Name))
allocateEipAddressArgs := &ecs.AllocateEipAddressArgs{
RegionId: common.Region(t.Cloud.Region()),
}
eipAddress, allocationId, err := t.Cloud.VpcClient().AllocateEipAddress(allocateEipAddressArgs)
if err != nil {
return fmt.Errorf("error creating eip: %v", err)
}
e.IpAddress = fi.String(eipAddress)
e.ID = fi.String(allocationId)
e.Available = fi.Bool(true)
}
associateEipAddressArgs := &ecs.AssociateEipAddressArgs{
AllocationId: fi.StringValue(e.ID),
InstanceId: fi.StringValue(e.NatGateway.ID),
InstanceType: ecs.Nat,
}
if fi.BoolValue(e.Available) {
err := t.Cloud.VpcClient().NewAssociateEipAddress(associateEipAddressArgs)
if err != nil {
return fmt.Errorf("error associating eip to natGateway: %v", err)
}
}
return nil
}
type terraformEip struct {
}
type terraformEipAssociation struct {
InstanceID *terraform.Literal `json:"instance_id,omitempty"`
AllocationID *terraform.Literal `json:"allocation_id,omitempty"`
}
func (_ *EIP) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *EIP) error {
tf := &terraformEip{}
err := t.RenderResource("alicloud_eip", *e.Name, tf)
if err != nil {
return err
}
associationtf := &terraformEipAssociation{
InstanceID: e.NatGateway.TerraformLink(),
AllocationID: e.TerraformLink(),
}
return t.RenderResource("alicloud_eip_association", *e.Name+"_asso", associationtf)
}
func (e *EIP) TerraformLink() *terraform.Literal {
return terraform.LiteralProperty("alicloud_eip", *e.Name, "id")
}

View File

@ -0,0 +1,129 @@
/*
Copyright 2019 The Kubernetes Authors.
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 alitasks
import (
"fmt"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"github.com/golang/glog"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/aliup"
"k8s.io/kops/upup/pkg/fi/cloudup/terraform"
)
//go:generate fitask -type=NatGateway
type NatGateway struct {
Name *string
Lifecycle *fi.Lifecycle
VPC *VPC
Region *string
ID *string
}
var _ fi.CompareWithID = &NatGateway{}
func (e *NatGateway) CompareWithID() *string {
return e.ID
}
func (e *NatGateway) Find(c *fi.Context) (*NatGateway, error) {
if e.VPC == nil || e.VPC.ID == nil {
glog.V(4).Infof("VPC / VPCID not found for %s, skipping Find", fi.StringValue(e.Name))
return nil, nil
}
cloud := c.Cloud.(aliup.ALICloud)
request := &ecs.DescribeNatGatewaysArgs{
RegionId: common.Region(cloud.Region()),
VpcId: fi.StringValue(e.VPC.ID),
}
natGateways, _, err := cloud.VpcClient().DescribeNatGateways(request)
if err != nil {
return nil, fmt.Errorf("error listing NatGateways: %v", err)
}
// Don't exist NatGateways with specified VPC.
if len(natGateways) == 0 {
return nil, nil
}
if len(natGateways) != 1 {
return nil, fmt.Errorf("found multiple NatGateways for %q", fi.StringValue(e.ID))
}
actual := &NatGateway{}
actual.ID = fi.String(natGateways[0].NatGatewayId)
// Ignore "system" fields
actual.Lifecycle = e.Lifecycle
actual.Name = e.Name
actual.Region = e.Region
e.ID = actual.ID
glog.V(4).Infof("found matching NatGateway %v", actual)
return actual, nil
}
func (s *NatGateway) CheckChanges(a, e, changes *NatGateway) error {
if a == nil {
if e.Name == nil {
return fi.RequiredField("Name")
}
}
return nil
}
func (e *NatGateway) Run(c *fi.Context) error {
return fi.DefaultDeltaRunMethod(e, c)
}
func (_ *NatGateway) RenderALI(t *aliup.ALIAPITarget, a, e, changes *NatGateway) error {
if a == nil {
request := &ecs.CreateNatGatewayArgs{
RegionId: common.Region(t.Cloud.Region()),
VpcId: fi.StringValue(e.VPC.ID),
Name: fi.StringValue(e.Name),
}
response, err := t.Cloud.VpcClient().CreateNatGateway(request)
if err != nil {
return fmt.Errorf("error creating NatGateway: %v", err)
}
e.ID = fi.String(response.NatGatewayId)
}
return nil
}
type terraformNatGateway struct {
Name *string `json:"name,omitempty"`
VpcId *terraform.Literal `json:"vpc_id,omitempty"`
}
func (_ *NatGateway) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *NatGateway) error {
tf := &terraformNatGateway{
Name: e.Name,
VpcId: e.VPC.TerraformLink(),
}
return t.RenderResource("alicloud_nat_gateway", *e.Name, tf)
}
func (e *NatGateway) TerraformLink() *terraform.Literal {
return terraform.LiteralProperty("alicloud_nat_gateway", *e.Name, "id")
}

View File

@ -0,0 +1,75 @@
/*
Copyright 2018 The Kubernetes Authors.
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.
*/
// Code generated by ""fitask" -type=NatGateway"; DO NOT EDIT
package alitasks
import (
"encoding/json"
"k8s.io/kops/upup/pkg/fi"
)
// NatGateway
// JSON marshaling boilerplate
type realNatGateway NatGateway
// UnmarshalJSON implements conversion to JSON, supporting an alternate specification of the object as a string
func (o *NatGateway) UnmarshalJSON(data []byte) error {
var jsonName string
if err := json.Unmarshal(data, &jsonName); err == nil {
o.Name = &jsonName
return nil
}
var r realNatGateway
if err := json.Unmarshal(data, &r); err != nil {
return err
}
*o = NatGateway(r)
return nil
}
var _ fi.HasLifecycle = &NatGateway{}
// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *NatGateway) GetLifecycle() *fi.Lifecycle {
return o.Lifecycle
}
// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *NatGateway) SetLifecycle(lifecycle fi.Lifecycle) {
o.Lifecycle = &lifecycle
}
var _ fi.HasName = &NatGateway{}
// GetName returns the Name of the object, implementing fi.HasName
func (o *NatGateway) GetName() *string {
return o.Name
}
// SetName sets the Name of the object, implementing fi.SetName
func (o *NatGateway) SetName(name string) {
o.Name = &name
}
// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *NatGateway) String() string {
return fi.TaskAsString(o)
}

View File

@ -0,0 +1,175 @@
/*
Copyright 2019 The Kubernetes Authors.
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 alitasks
import (
"fmt"
"github.com/golang/glog"
"github.com/denverdino/aliyungo/common"
"github.com/denverdino/aliyungo/ecs"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/aliup"
"k8s.io/kops/upup/pkg/fi/cloudup/terraform"
)
//go:generate fitask -type=VSwitchSNAT
type VSwitchSNAT struct {
Name *string
Lifecycle *fi.Lifecycle
ID *string
VSwitch *VSwitch
NatGateway *NatGateway
EIP *EIP
SnatTableId *string
// Shared is set if this is a shared VSwitch
Shared *bool
}
var _ fi.CompareWithID = &VSwitchSNAT{}
func (v *VSwitchSNAT) CompareWithID() *string {
return v.Name
}
func (v *VSwitchSNAT) Find(c *fi.Context) (*VSwitchSNAT, error) {
if v.VSwitch == nil || v.VSwitch.VSwitchId == nil {
glog.V(4).Infof("VSwitch / VSwitchId not found for %s, skipping Find", fi.StringValue(v.Name))
return nil, nil
}
if v.NatGateway == nil || v.NatGateway.ID == nil {
glog.V(4).Infof("NatGateway / NatGatewayId not found for %s, skipping Find", fi.StringValue(v.Name))
return nil, nil
}
if v.EIP == nil || v.EIP.IpAddress == nil {
glog.V(4).Infof("EIP / EIP not found for %s, skipping Find", fi.StringValue(v.Name))
return nil, nil
}
cloud := c.Cloud.(aliup.ALICloud)
describeNatGatewaysArgs := &ecs.DescribeNatGatewaysArgs{
RegionId: common.Region(cloud.Region()),
NatGatewayId: fi.StringValue(v.NatGateway.ID),
}
natGateways, _, err := cloud.VpcClient().DescribeNatGateways(describeNatGatewaysArgs)
if err != nil {
return nil, fmt.Errorf("error listing NatGateways: %v", err)
}
if len(natGateways) == 0 {
glog.V(4).Infof("NatGateway not found for %s, skipping Find", fi.StringValue(v.Name))
return nil, nil
}
if len(natGateways[0].SnatTableIds.SnatTableId) == 0 {
return nil, nil
}
for _, snatTableId := range natGateways[0].SnatTableIds.SnatTableId {
describeSnatTableEntriesArgs := &ecs.DescribeSnatTableEntriesArgs{
RegionId: common.Region(cloud.Region()),
SnatTableId: snatTableId,
}
snatTableEntries, _, err := cloud.VpcClient().DescribeSnatTableEntries(describeSnatTableEntriesArgs)
if err != nil {
return nil, fmt.Errorf("error listing snatTableEntries: %v", err)
}
if len(snatTableEntries) == 0 {
continue
}
for _, snatEntry := range snatTableEntries {
if snatEntry.SourceVSwitchId == fi.StringValue(v.VSwitch.VSwitchId) {
actual := &VSwitchSNAT{}
actual.ID = fi.String(snatEntry.SnatEntryId)
v.ID = actual.ID
actual.VSwitch = v.VSwitch
actual.NatGateway = &NatGateway{ID: v.NatGateway.ID}
actual.SnatTableId = fi.String(snatTableId)
v.SnatTableId = actual.SnatTableId
// Prevent spurious changes
actual.Shared = v.Shared
actual.Name = v.Name
actual.Lifecycle = v.Lifecycle
return actual, nil
}
}
}
v.SnatTableId = fi.String(natGateways[0].SnatTableIds.SnatTableId[0])
return nil, nil
}
func (v *VSwitchSNAT) Run(c *fi.Context) error {
return fi.DefaultDeltaRunMethod(v, c)
}
func (v *VSwitchSNAT) CheckChanges(a, e, changes *VSwitchSNAT) error {
if e.VSwitch == nil {
return fi.RequiredField("VPC")
}
if e.NatGateway == nil {
return fi.RequiredField("CIDRBlock")
}
if a != nil && changes != nil {
if changes.VSwitch != nil {
return fi.CannotChangeField("VSwitch")
}
if changes.NatGateway != nil {
return fi.CannotChangeField("NatGateway")
}
}
return nil
}
func (_ *VSwitchSNAT) RenderALI(t *aliup.ALIAPITarget, a, e, changes *VSwitchSNAT) error {
if a == nil {
createSnatEntryArgs := &ecs.CreateSnatEntryArgs{
RegionId: common.Region(t.Cloud.Region()),
SnatTableId: fi.StringValue(e.SnatTableId),
SourceVSwitchId: fi.StringValue(e.VSwitch.VSwitchId),
SnatIp: fi.StringValue(e.EIP.IpAddress),
}
resp, err := t.Cloud.VpcClient().CreateSnatEntry(createSnatEntryArgs)
if err != nil {
return fmt.Errorf("error creating SnatEntry: %v,%v", err, createSnatEntryArgs)
}
e.ID = fi.String(resp.SnatEntryId)
}
return nil
}
type terraformVSwitchSNAT struct {
SnatTableId *string `json:"snat_table_id,omitempty"`
VSwitchId *terraform.Literal `json:"source_vswitch_id,omitempty"`
}
func (_ *VSwitchSNAT) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *VSwitchSNAT) error {
tf := &terraformVSwitchSNAT{
SnatTableId: e.SnatTableId,
VSwitchId: e.VSwitch.TerraformLink(),
}
return t.RenderResource("alicloud_snat_entry", *e.Name, tf)
}

View File

@ -0,0 +1,75 @@
/*
Copyright 2018 The Kubernetes Authors.
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.
*/
// Code generated by ""fitask" -type=VSwitchSNAT"; DO NOT EDIT
package alitasks
import (
"encoding/json"
"k8s.io/kops/upup/pkg/fi"
)
// VSwitchSNAT
// JSON marshaling boilerplate
type realVSwitchSNAT VSwitchSNAT
// UnmarshalJSON implements conversion to JSON, supporting an alternate specification of the object as a string
func (o *VSwitchSNAT) UnmarshalJSON(data []byte) error {
var jsonName string
if err := json.Unmarshal(data, &jsonName); err == nil {
o.Name = &jsonName
return nil
}
var r realVSwitchSNAT
if err := json.Unmarshal(data, &r); err != nil {
return err
}
*o = VSwitchSNAT(r)
return nil
}
var _ fi.HasLifecycle = &VSwitchSNAT{}
// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle
func (o *VSwitchSNAT) GetLifecycle() *fi.Lifecycle {
return o.Lifecycle
}
// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle
func (o *VSwitchSNAT) SetLifecycle(lifecycle fi.Lifecycle) {
o.Lifecycle = &lifecycle
}
var _ fi.HasName = &VSwitchSNAT{}
// GetName returns the Name of the object, implementing fi.HasName
func (o *VSwitchSNAT) GetName() *string {
return o.Name
}
// SetName sets the Name of the object, implementing fi.SetName
func (o *VSwitchSNAT) SetName(name string) {
o.Name = &name
}
// String is the stringer function for the task, producing readable output using fi.TaskAsString
func (o *VSwitchSNAT) String() string {
return fi.TaskAsString(o)
}

View File

@ -51,6 +51,7 @@ type ALICloud interface {
SlbClient() *slb.Client SlbClient() *slb.Client
RamClient() *ram.RamClient RamClient() *ram.RamClient
EssClient() *ess.Client EssClient() *ess.Client
VpcClient() *ecs.Client
Region() string Region() string
AddClusterTags(tags map[string]string) AddClusterTags(tags map[string]string)
@ -67,6 +68,7 @@ type aliCloudImplementation struct {
slbClient *slb.Client slbClient *slb.Client
ramClient *ram.RamClient ramClient *ram.RamClient
essClient *ess.Client essClient *ess.Client
vpcClient *ecs.Client
region string region string
tags map[string]string tags map[string]string
@ -95,6 +97,7 @@ func NewALICloud(region string, tags map[string]string) (ALICloud, error) {
ramclient := ram.NewClient(accessKeyId, accessKeySecret) ramclient := ram.NewClient(accessKeyId, accessKeySecret)
c.ramClient = ramclient.(*ram.RamClient) c.ramClient = ramclient.(*ram.RamClient)
c.essClient = ess.NewClient(accessKeyId, accessKeySecret) c.essClient = ess.NewClient(accessKeyId, accessKeySecret)
c.vpcClient = ecs.NewVPCClient(accessKeyId, accessKeySecret, common.Region(region))
c.tags = tags c.tags = tags
@ -117,6 +120,10 @@ func (c *aliCloudImplementation) EssClient() *ess.Client {
return c.essClient return c.essClient
} }
func (c *aliCloudImplementation) VpcClient() *ecs.Client {
return c.vpcClient
}
func (c *aliCloudImplementation) Region() string { func (c *aliCloudImplementation) Region() string {
return c.region return c.region
} }