Merge pull request #13853 from akkina2107/Truncate-cluster-name

Fix openstack tag limitation
This commit is contained in:
Kubernetes Prow Robot 2022-09-06 12:56:23 -07:00 committed by GitHub
commit 3980383aa1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 509 additions and 4 deletions

View File

@ -26,6 +26,7 @@ import (
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/dns"
"k8s.io/kops/pkg/model"
"k8s.io/kops/pkg/truncate"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
"k8s.io/kops/upup/pkg/fi/cloudup/openstacktasks"
@ -44,6 +45,15 @@ var _ fi.ModelBuilder = &ServerGroupModelBuilder{}
// See https://specs.openstack.org/openstack/nova-specs/specs/newton/approved/lowercase-metadata-keys.html for details
var instanceMetadataNotAllowedCharacters = regexp.MustCompile("[^a-zA-Z0-9-_:. ]")
// Constants for truncating Tags
const MAX_TAG_LENGTH_OPENSTACK = 60
var TRUNCATE_OPT = truncate.TruncateStringOptions{
MaxLength: MAX_TAG_LENGTH_OPENSTACK,
AlwaysAddHash: false,
HashLength: 6,
}
func (b *ServerGroupModelBuilder) buildInstances(c *fi.ModelBuilderContext, sg *openstacktasks.ServerGroup, ig *kops.InstanceGroup) error {
sshKeyNameFull, err := b.SSHKeyName()
if err != nil {
@ -146,9 +156,9 @@ func (b *ServerGroupModelBuilder) buildInstances(c *fi.ModelBuilderContext, sg *
InstanceGroupName: &groupName,
Network: b.LinkToNetwork(),
Tags: []string{
fmt.Sprintf("%s=%s", openstack.TagKopsInstanceGroup, groupName),
fmt.Sprintf("%s=%s", openstack.TagKopsName, portTagKopsName),
fmt.Sprintf("%s=%s", openstack.TagClusterName, b.ClusterName()),
truncate.TruncateString(fmt.Sprintf("%s=%s", openstack.TagKopsInstanceGroup, groupName), TRUNCATE_OPT),
truncate.TruncateString(fmt.Sprintf("%s=%s", openstack.TagKopsName, portTagKopsName), TRUNCATE_OPT),
truncate.TruncateString(fmt.Sprintf("%s=%s", openstack.TagClusterName, b.ClusterName()), TRUNCATE_OPT),
},
SecurityGroups: securityGroups,
AdditionalSecurityGroups: ig.Spec.AdditionalSecurityGroups,

View File

@ -308,6 +308,64 @@ func getServerGroupModelBuilderTestInput() []serverGroupModelBuilderTestInput {
},
},
},
{
desc: "truncate cluster names to 42 characters",
cluster: &kops.Cluster{
ObjectMeta: metav1.ObjectMeta{
Name: "tom-software-dev-playground-real33-k8s-local",
},
Spec: kops.ClusterSpec{
MasterPublicName: "master-public-name",
CloudProvider: kops.CloudProviderSpec{
Openstack: &kops.OpenstackSpec{
Router: &kops.OpenstackRouter{
ExternalNetwork: fi.String("test"),
},
Metadata: &kops.OpenstackMetadata{
ConfigDrive: fi.Bool(false),
},
},
},
KubernetesVersion: "1.24.0",
Subnets: []kops.ClusterSubnetSpec{
{
Name: "subnet",
Region: "region",
},
},
},
},
instanceGroups: []*kops.InstanceGroup{
{
ObjectMeta: metav1.ObjectMeta{
Name: "master",
},
Spec: kops.InstanceGroupSpec{
Role: kops.InstanceGroupRoleMaster,
Image: "image-master",
MinSize: i32(1),
MaxSize: i32(1),
MachineType: "blc.1-2",
Subnets: []string{"subnet"},
Zones: []string{"zone-1"},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "node",
},
Spec: kops.InstanceGroupSpec{
Role: kops.InstanceGroupRoleNode,
Image: "image-node",
MinSize: i32(1),
MaxSize: i32(1),
MachineType: "blc.2-4",
Subnets: []string{"subnet"},
Zones: []string{"zone-1"},
},
},
},
},
{
desc: "multizone setup 3 masters 3 nodes without bastion with API loadbalancer",
cluster: &kops.Cluster{

View File

@ -0,0 +1,393 @@
Lifecycle: ""
Name: master
---
Lifecycle: ""
Name: node
---
ForAPIServer: true
ID: null
IP: null
LB: null
Lifecycle: Sync
Name: fip-master-1-tom-software-dev-playground-real33-k8s-local
---
ForAPIServer: false
ID: null
IP: null
LB: null
Lifecycle: Sync
Name: fip-node-1-tom-software-dev-playground-real33-k8s-local
---
AvailabilityZone: zone-1
ConfigDrive: false
Flavor: blc.1-2
FloatingIP:
ForAPIServer: true
ID: null
IP: null
LB: null
Lifecycle: Sync
Name: fip-master-1-tom-software-dev-playground-real33-k8s-local
ForAPIServer: false
GroupName: master
ID: null
Image: image-master
Lifecycle: Sync
Metadata:
KopsInstanceGroup: master
KopsName: master-1-tom-software-dev-playground-real33-k8s-local
KopsNetwork: tom-software-dev-playground-real33-k8s-local
KopsRole: Master
KubernetesCluster: tom-software-dev-playground-real33-k8s-local
cluster_generation: "0"
ig_generation: "0"
k8s: tom-software-dev-playground-real33-k8s-local
k8s.io_cluster-autoscaler_node-template_label_kops.k8s.io_kops-controller-pki: ""
k8s.io_cluster-autoscaler_node-template_label_node-role.kubernetes.io_control-plane: ""
k8s.io_cluster-autoscaler_node-template_label_node.kubernetes.io_exclude-from-external-load-balancers: ""
k8s.io_role_master: "1"
kops.k8s.io_instancegroup: master
Name: master-1-tom-software-dev-playground-real33-k8s-local
Port:
AdditionalSecurityGroups: null
ID: null
InstanceGroupName: master
Lifecycle: Sync
Name: port-master-1-tom-software-dev-playground-real33-k8s-local
Network:
AvailabilityZoneHints: null
ID: null
Lifecycle: ""
Name: tom-software-dev-playground-real33-k8s-local
Tag: null
SecurityGroups:
- Description: null
ID: null
Lifecycle: ""
Name: masters.tom-software-dev-playground-real33-k8s-local
RemoveExtraRules: null
RemoveGroup: false
- Description: null
ID: null
Lifecycle: ""
Name: master-public-name
RemoveExtraRules: null
RemoveGroup: false
Subnets:
- CIDR: null
DNSServers: null
ID: null
Lifecycle: ""
Name: subnet.tom-software-dev-playground-real33-k8s-local
Network: null
Tag: null
Tags:
- KopsInstanceGroup=master
- KopsName=port-master-1
- KubernetesCluster=tom-software-dev-playground-real33--kngu8l
Region: region
Role: Master
SSHKey: kubernetes.tom-software-dev-playground-real33-k8s-local-ba_d8_85_a0_5b_50_b0_01_e0_b2_b0_ae_5d_f6_7a_d1
SecurityGroups: null
ServerGroup:
ClusterName: tom-software-dev-playground-real33-k8s-local
ID: null
IGName: master
Lifecycle: Sync
MaxSize: 1
Name: tom-software-dev-playground-real33-k8s-local-master
Policies:
- anti-affinity
UserData:
task:
Lifecycle: ""
Name: master
---
AvailabilityZone: zone-1
ConfigDrive: false
Flavor: blc.2-4
FloatingIP:
ForAPIServer: false
ID: null
IP: null
LB: null
Lifecycle: Sync
Name: fip-node-1-tom-software-dev-playground-real33-k8s-local
ForAPIServer: false
GroupName: node
ID: null
Image: image-node
Lifecycle: Sync
Metadata:
KopsInstanceGroup: node
KopsName: node-1-tom-software-dev-playground-real33-k8s-local
KopsNetwork: tom-software-dev-playground-real33-k8s-local
KopsRole: Node
KubernetesCluster: tom-software-dev-playground-real33-k8s-local
cluster_generation: "0"
ig_generation: "0"
k8s: tom-software-dev-playground-real33-k8s-local
k8s.io_cluster-autoscaler_node-template_label_node-role.kubernetes.io_node: ""
k8s.io_role_node: "1"
kops.k8s.io_instancegroup: node
Name: node-1-tom-software-dev-playground-real33-k8s-local
Port:
AdditionalSecurityGroups: null
ID: null
InstanceGroupName: node
Lifecycle: Sync
Name: port-node-1-tom-software-dev-playground-real33-k8s-local
Network:
AvailabilityZoneHints: null
ID: null
Lifecycle: ""
Name: tom-software-dev-playground-real33-k8s-local
Tag: null
SecurityGroups:
- Description: null
ID: null
Lifecycle: ""
Name: nodes.tom-software-dev-playground-real33-k8s-local
RemoveExtraRules: null
RemoveGroup: false
Subnets:
- CIDR: null
DNSServers: null
ID: null
Lifecycle: ""
Name: subnet.tom-software-dev-playground-real33-k8s-local
Network: null
Tag: null
Tags:
- KopsInstanceGroup=node
- KopsName=port-node-1
- KubernetesCluster=tom-software-dev-playground-real33--kngu8l
Region: region
Role: Node
SSHKey: kubernetes.tom-software-dev-playground-real33-k8s-local-ba_d8_85_a0_5b_50_b0_01_e0_b2_b0_ae_5d_f6_7a_d1
SecurityGroups: null
ServerGroup:
ClusterName: tom-software-dev-playground-real33-k8s-local
ID: null
IGName: node
Lifecycle: Sync
MaxSize: 1
Name: tom-software-dev-playground-real33-k8s-local-node
Policies:
- anti-affinity
UserData:
task:
Lifecycle: ""
Name: node
---
Lifecycle: ""
Name: apiserver-aggregator-ca
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=apiserver-aggregator-ca
type: ca
---
Lifecycle: ""
Name: etcd-clients-ca
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=etcd-clients-ca
type: ca
---
Lifecycle: ""
Name: etcd-manager-ca-events
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=etcd-manager-ca-events
type: ca
---
Lifecycle: ""
Name: etcd-manager-ca-main
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=etcd-manager-ca-main
type: ca
---
Lifecycle: ""
Name: etcd-peers-ca-events
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=etcd-peers-ca-events
type: ca
---
Lifecycle: ""
Name: etcd-peers-ca-main
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=etcd-peers-ca-main
type: ca
---
Lifecycle: ""
Name: kube-proxy
Signer:
Lifecycle: ""
Name: kubernetes-ca
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=kubernetes
type: ca
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=kube-proxy
type: client
---
Lifecycle: ""
Name: kubelet
Signer:
Lifecycle: ""
Name: kubernetes-ca
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=kubernetes
type: ca
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=kubelet
type: client
---
Lifecycle: ""
Name: kubernetes-ca
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=kubernetes
type: ca
---
Lifecycle: ""
Name: service-account
Signer: null
alternateNames: null
issuer: ""
oldFormat: false
subject: cn=service-account
type: ca
---
Base: null
Contents:
task:
Lifecycle: ""
Name: master
Lifecycle: ""
Location: igconfig/master/master/nodeupconfig.yaml
Name: nodeupconfig-master
Public: null
---
Base: null
Contents:
task:
Lifecycle: ""
Name: node
Lifecycle: ""
Location: igconfig/node/node/nodeupconfig.yaml
Name: nodeupconfig-node
Public: null
---
AdditionalSecurityGroups: null
ID: null
InstanceGroupName: master
Lifecycle: Sync
Name: port-master-1-tom-software-dev-playground-real33-k8s-local
Network:
AvailabilityZoneHints: null
ID: null
Lifecycle: ""
Name: tom-software-dev-playground-real33-k8s-local
Tag: null
SecurityGroups:
- Description: null
ID: null
Lifecycle: ""
Name: masters.tom-software-dev-playground-real33-k8s-local
RemoveExtraRules: null
RemoveGroup: false
- Description: null
ID: null
Lifecycle: ""
Name: master-public-name
RemoveExtraRules: null
RemoveGroup: false
Subnets:
- CIDR: null
DNSServers: null
ID: null
Lifecycle: ""
Name: subnet.tom-software-dev-playground-real33-k8s-local
Network: null
Tag: null
Tags:
- KopsInstanceGroup=master
- KopsName=port-master-1
- KubernetesCluster=tom-software-dev-playground-real33--kngu8l
---
AdditionalSecurityGroups: null
ID: null
InstanceGroupName: node
Lifecycle: Sync
Name: port-node-1-tom-software-dev-playground-real33-k8s-local
Network:
AvailabilityZoneHints: null
ID: null
Lifecycle: ""
Name: tom-software-dev-playground-real33-k8s-local
Tag: null
SecurityGroups:
- Description: null
ID: null
Lifecycle: ""
Name: nodes.tom-software-dev-playground-real33-k8s-local
RemoveExtraRules: null
RemoveGroup: false
Subnets:
- CIDR: null
DNSServers: null
ID: null
Lifecycle: ""
Name: subnet.tom-software-dev-playground-real33-k8s-local
Network: null
Tag: null
Tags:
- KopsInstanceGroup=node
- KopsName=port-node-1
- KubernetesCluster=tom-software-dev-playground-real33--kngu8l
---
ClusterName: tom-software-dev-playground-real33-k8s-local
ID: null
IGName: master
Lifecycle: Sync
MaxSize: 1
Name: tom-software-dev-playground-real33-k8s-local-master
Policies:
- anti-affinity
---
ClusterName: tom-software-dev-playground-real33-k8s-local
ID: null
IGName: node
Lifecycle: Sync
MaxSize: 1
Name: tom-software-dev-playground-real33-k8s-local-node
Policies:
- anti-affinity

View File

@ -29,6 +29,7 @@ import (
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/schedulerhints"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/truncate"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
)
@ -62,6 +63,15 @@ var (
_ fi.HasDependencies = &Instance{}
)
// Constants for truncating Tags
const MAX_TAG_LENGTH_OPENSTACK = 60
var TRUNCATE_OPT = truncate.TruncateStringOptions{
MaxLength: MAX_TAG_LENGTH_OPENSTACK,
AlwaysAddHash: false,
HashLength: 6,
}
// GetDependencies returns the dependencies of the Instance task
func (e *Instance) GetDependencies(tasks map[string]fi.Task) []fi.Task {
var deps []fi.Task
@ -119,7 +129,7 @@ func (e *Instance) FindAddresses(context *fi.Context) ([]string, error) {
// filterInstancePorts tries to get all ports of an instance tagged with the cluster name.
// If no tagged ports are found it will return all ports of the instance, to not change the legacy behavior when there weren't tagged ports
func filterInstancePorts(allPorts []ports.Port, clusterName string) []ports.Port {
clusterNameTag := fmt.Sprintf("%s=%s", openstack.TagClusterName, clusterName)
clusterNameTag := truncate.TruncateString(fmt.Sprintf("%s=%s", openstack.TagClusterName, clusterName), TRUNCATE_OPT)
var taggedPorts []ports.Port

View File

@ -22,6 +22,7 @@ import (
"testing"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"k8s.io/kops/pkg/truncate"
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
)
@ -102,3 +103,36 @@ func TestFilterPortsReturnsOnlyTaggedPorts(t *testing.T) {
t.Fatalf("expected '%+v', but got '%+v", expectedPorts, actualPorts)
}
}
func TestFilterPortsReturnsOnlyTaggedPortsWithLongClustername(t *testing.T) {
clusterName := "tom-software-dev-playground-real33-k8s-local"
clusterNameTag := truncate.TruncateString(fmt.Sprintf("%s=%s", openstack.TagClusterName, clusterName), TRUNCATE_OPT)
allPorts := []ports.Port{
{
ID: "fakeID_1",
Tags: []string{
clusterNameTag,
},
},
{
ID: "fakeID_2",
},
{
ID: "fakeID_3",
Tags: []string{
clusterNameTag,
},
},
}
expectedPorts := []ports.Port{
allPorts[0],
allPorts[2],
}
actualPorts := filterInstancePorts(allPorts, clusterName)
if !reflect.DeepEqual(expectedPorts, actualPorts) {
t.Fatalf("expected '%+v', but got '%+v", expectedPorts, actualPorts)
}
}