mirror of https://github.com/kubernetes/kops.git
add natGateways tasks for ALICloud
This commit is contained in:
parent
ae6cda7bb1
commit
dafbc17c5a
|
@ -49,6 +49,33 @@ func (c *ALIModelContext) GetNameForVSwitch(subnetName string) string {
|
|||
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
|
||||
func (c *ALIModelContext) LinkLoadBalancer() *alitasks.LoadBalancer {
|
||||
return &alitasks.LoadBalancer{Name: s(c.GetNameForLoadBalancer())}
|
||||
|
|
|
@ -50,6 +50,21 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
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 {
|
||||
subnetSpec := &b.Cluster.Spec.Subnets[i]
|
||||
|
||||
|
@ -69,6 +84,20 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
|
||||
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
|
||||
|
|
|
@ -48,6 +48,8 @@ const (
|
|||
typeVolume = "Volume"
|
||||
typeSSHKey = "SSHKey"
|
||||
typeVPC = "VPC"
|
||||
typeNatGateway = "NatGateway"
|
||||
typeEIP = "EIP"
|
||||
)
|
||||
|
||||
type clusterDiscoveryALI struct {
|
||||
|
@ -596,6 +598,8 @@ func (d *clusterDiscoveryALI) ListVPC() ([]*resources.Resource, error) {
|
|||
}
|
||||
resourceTrackers = append(resourceTrackers, resourceTracker)
|
||||
}
|
||||
|
||||
ListNatGateway(d, vpcsToDelete[0], &resourceTrackers)
|
||||
}
|
||||
|
||||
return resourceTrackers, nil
|
||||
|
@ -689,3 +693,138 @@ func DeleteVolume(cloud fi.Cloud, r *resources.Resource) error {
|
|||
}
|
||||
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
|
||||
}
|
||||
|
|
|
@ -11,11 +11,13 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/apis/kops:go_default_library",
|
||||
"//pkg/resources:go_default_library",
|
||||
"//pkg/resources/ali:go_default_library",
|
||||
"//pkg/resources/aws:go_default_library",
|
||||
"//pkg/resources/digitalocean:go_default_library",
|
||||
"//pkg/resources/gce:go_default_library",
|
||||
"//pkg/resources/openstack: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/gce:go_default_library",
|
||||
"//upup/pkg/fi/cloudup/openstack:go_default_library",
|
||||
|
|
|
@ -21,11 +21,13 @@ import (
|
|||
|
||||
"k8s.io/kops/pkg/apis/kops"
|
||||
"k8s.io/kops/pkg/resources"
|
||||
"k8s.io/kops/pkg/resources/ali"
|
||||
"k8s.io/kops/pkg/resources/aws"
|
||||
"k8s.io/kops/pkg/resources/digitalocean"
|
||||
"k8s.io/kops/pkg/resources/gce"
|
||||
"k8s.io/kops/pkg/resources/openstack"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
cloudali "k8s.io/kops/upup/pkg/fi/cloudup/aliup"
|
||||
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
|
||||
cloudgce "k8s.io/kops/upup/pkg/fi/cloudup/gce"
|
||||
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)
|
||||
case kops.CloudProviderVSphere:
|
||||
return resources.ListResourcesVSphere(cloud.(*vsphere.VSphereCloud), clusterName)
|
||||
case kops.CloudProviderALI:
|
||||
return ali.ListResourcesALI(cloud.(cloudali.ALICloud), clusterName, region)
|
||||
default:
|
||||
return nil, fmt.Errorf("delete on clusters on %q not (yet) supported", cloud.ProviderID())
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ go_library(
|
|||
srcs = [
|
||||
"disk.go",
|
||||
"disk_fitask.go",
|
||||
"eip_fitask.go",
|
||||
"eip_natgateway_association.go",
|
||||
"launchconfiguration.go",
|
||||
"launchconfiguration_fitask.go",
|
||||
"loadbalancer.go",
|
||||
|
@ -13,6 +15,8 @@ go_library(
|
|||
"loadbalancerlistener_fitask.go",
|
||||
"loadbalancerwhitelist.go",
|
||||
"loadbalancerwhitelist_fitask.go",
|
||||
"natgateway.go",
|
||||
"natgateway_fitask.go",
|
||||
"rampolicy.go",
|
||||
"rampolicy_fitask.go",
|
||||
"ramrole.go",
|
||||
|
@ -28,7 +32,9 @@ go_library(
|
|||
"vpc.go",
|
||||
"vpc_fitask.go",
|
||||
"vswitch.go",
|
||||
"vswitchSNAT.go",
|
||||
"vswitch_fitask.go",
|
||||
"vswitchsnat_fitask.go",
|
||||
],
|
||||
importpath = "k8s.io/kops/upup/pkg/fi/cloudup/alitasks",
|
||||
visibility = ["//visibility:public"],
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -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")
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -51,6 +51,7 @@ type ALICloud interface {
|
|||
SlbClient() *slb.Client
|
||||
RamClient() *ram.RamClient
|
||||
EssClient() *ess.Client
|
||||
VpcClient() *ecs.Client
|
||||
|
||||
Region() string
|
||||
AddClusterTags(tags map[string]string)
|
||||
|
@ -67,6 +68,7 @@ type aliCloudImplementation struct {
|
|||
slbClient *slb.Client
|
||||
ramClient *ram.RamClient
|
||||
essClient *ess.Client
|
||||
vpcClient *ecs.Client
|
||||
|
||||
region string
|
||||
tags map[string]string
|
||||
|
@ -95,6 +97,7 @@ func NewALICloud(region string, tags map[string]string) (ALICloud, error) {
|
|||
ramclient := ram.NewClient(accessKeyId, accessKeySecret)
|
||||
c.ramClient = ramclient.(*ram.RamClient)
|
||||
c.essClient = ess.NewClient(accessKeyId, accessKeySecret)
|
||||
c.vpcClient = ecs.NewVPCClient(accessKeyId, accessKeySecret, common.Region(region))
|
||||
|
||||
c.tags = tags
|
||||
|
||||
|
@ -117,6 +120,10 @@ func (c *aliCloudImplementation) EssClient() *ess.Client {
|
|||
return c.essClient
|
||||
}
|
||||
|
||||
func (c *aliCloudImplementation) VpcClient() *ecs.Client {
|
||||
return c.vpcClient
|
||||
}
|
||||
|
||||
func (c *aliCloudImplementation) Region() string {
|
||||
return c.region
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue