diff --git a/pkg/cloudprovider/aws/apis/v1alpha1/tags.go b/pkg/cloudprovider/aws/apis/v1alpha1/tags.go index 08d8d9804a42..64006ce2159f 100644 --- a/pkg/cloudprovider/aws/apis/v1alpha1/tags.go +++ b/pkg/cloudprovider/aws/apis/v1alpha1/tags.go @@ -28,8 +28,14 @@ import ( func MergeTags(ctx context.Context, custom ...map[string]string) (result []*ec2.Tag) { tags := map[string]string{ + // karpenter.sh/provisioner-name: v1alpha5.ProvisionerNameLabelKey: injection.GetNamespacedName(ctx).Name, - "Name": fmt.Sprintf("%s/%s", v1alpha5.ProvisionerNameLabelKey, injection.GetNamespacedName(ctx).Name), + // karpenter.sh/cluster/: owned + fmt.Sprintf("%s/cluster/%s", v1alpha5.Group, injection.GetOptions(ctx).ClusterName): "owned", + // kubernetes.io/cluster/: owned + fmt.Sprintf("kubernetes.io/cluster/%s", injection.GetOptions(ctx).ClusterName): "owned", + // Name: karpenter.sh/cluster//provisioner/ + "Name": fmt.Sprintf("%s/cluster/%s/provisioner/%s", v1alpha5.Group, injection.GetOptions(ctx).ClusterName, injection.GetNamespacedName(ctx).Name), } // Custom tags may override defaults (e.g. Name) for _, t := range custom { diff --git a/pkg/cloudprovider/aws/instance.go b/pkg/cloudprovider/aws/instance.go index dd6c96350478..3b8f69340731 100644 --- a/pkg/cloudprovider/aws/instance.go +++ b/pkg/cloudprovider/aws/instance.go @@ -137,7 +137,7 @@ func (p *InstanceProvider) launchInstances(ctx context.Context, constraints *v1a return nil, fmt.Errorf("getting launch template configs, %w", err) } // Create fleet - tags := v1alpha1.MergeTags(ctx, constraints.Tags, map[string]string{fmt.Sprintf("kubernetes.io/cluster/%s", injection.GetOptions(ctx).ClusterName): "owned"}) + tags := v1alpha1.MergeTags(ctx, constraints.Tags) createFleetInput := &ec2.CreateFleetInput{ Type: aws.String(ec2.FleetTypeInstant), LaunchTemplateConfigs: launchTemplateConfigs, @@ -148,6 +148,7 @@ func (p *InstanceProvider) launchInstances(ctx context.Context, constraints *v1a TagSpecifications: []*ec2.TagSpecification{ {ResourceType: aws.String(ec2.ResourceTypeInstance), Tags: tags}, {ResourceType: aws.String(ec2.ResourceTypeVolume), Tags: tags}, + {ResourceType: aws.String(ec2.ResourceTypeFleet), Tags: tags}, }, } if capacityType == v1alpha1.CapacityTypeSpot { diff --git a/pkg/cloudprovider/aws/suite_test.go b/pkg/cloudprovider/aws/suite_test.go index 34e2c61e7379..56a74c7aa61a 100644 --- a/pkg/cloudprovider/aws/suite_test.go +++ b/pkg/cloudprovider/aws/suite_test.go @@ -476,7 +476,7 @@ var _ = Describe("Allocation", func() { ExpectScheduled(ctx, env.Client, pod) Expect(fakeEC2API.CalledWithCreateFleetInput.Cardinality()).To(Equal(1)) createFleetInput := fakeEC2API.CalledWithCreateFleetInput.Pop().(*ec2.CreateFleetInput) - Expect(createFleetInput.TagSpecifications).To(HaveLen(2)) + Expect(createFleetInput.TagSpecifications).To(HaveLen(3)) // tags should be included in both the instance and volume tag specification Expect(*createFleetInput.TagSpecifications[0].ResourceType).To(Equal(ec2.ResourceTypeInstance)) @@ -497,7 +497,7 @@ var _ = Describe("Allocation", func() { ExpectScheduled(ctx, env.Client, pod) Expect(fakeEC2API.CalledWithCreateFleetInput.Cardinality()).To(Equal(1)) createFleetInput := fakeEC2API.CalledWithCreateFleetInput.Pop().(*ec2.CreateFleetInput) - Expect(createFleetInput.TagSpecifications).To(HaveLen(2)) + Expect(createFleetInput.TagSpecifications).To(HaveLen(3)) // tags should be included in both the instance and volume tag specification Expect(*createFleetInput.TagSpecifications[0].ResourceType).To(Equal(ec2.ResourceTypeInstance)) @@ -505,6 +505,41 @@ var _ = Describe("Allocation", func() { Expect(*createFleetInput.TagSpecifications[1].ResourceType).To(Equal(ec2.ResourceTypeVolume)) ExpectTags(createFleetInput.TagSpecifications[1].Tags, provider.Tags) + + Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput.Cardinality()).To(Equal(1)) + createLaunchTemplateInput := fakeEC2API.CalledWithCreateLaunchTemplateInput.Pop().(*ec2.CreateLaunchTemplateInput) + // default tags should be included in the LaunchTemplate specification + Expect(*createLaunchTemplateInput.TagSpecifications[0].ResourceType).To(Equal(ec2.ResourceTypeLaunchTemplate)) + ExpectTags(createLaunchTemplateInput.TagSpecifications[0].Tags, provider.Tags) + }) + + It("should apply default tags if not overriden", func() { + // default tags applied to all created resources + defaultTags := map[string]string{ + v1alpha5.ProvisionerNameLabelKey: provisioner.Name, + fmt.Sprintf("karpenter.sh/cluster/%s", opts.ClusterName): "owned", + fmt.Sprintf("kubernetes.io/cluster/%s", opts.ClusterName): "owned", + "Name": fmt.Sprintf("karpenter.sh/cluster/%s/provisioner/%s", opts.ClusterName, provisioner.Name), + } + + pod := ExpectProvisioned(ctx, env.Client, selectionController, provisioners, ProvisionerWithProvider(provisioner, provider), test.UnschedulablePod())[0] + ExpectScheduled(ctx, env.Client, pod) + Expect(fakeEC2API.CalledWithCreateFleetInput.Cardinality()).To(Equal(1)) + createFleetInput := fakeEC2API.CalledWithCreateFleetInput.Pop().(*ec2.CreateFleetInput) + Expect(createFleetInput.TagSpecifications).To(HaveLen(3)) + + // default tags should be included in the Instance specification + Expect(*createFleetInput.TagSpecifications[0].ResourceType).To(Equal(ec2.ResourceTypeInstance)) + ExpectTags(createFleetInput.TagSpecifications[0].Tags, defaultTags) + // default tags should be included in the Volume specification + Expect(*createFleetInput.TagSpecifications[1].ResourceType).To(Equal(ec2.ResourceTypeVolume)) + ExpectTags(createFleetInput.TagSpecifications[1].Tags, defaultTags) + + Expect(fakeEC2API.CalledWithCreateLaunchTemplateInput.Cardinality()).To(Equal(1)) + createLaunchTemplateInput := fakeEC2API.CalledWithCreateLaunchTemplateInput.Pop().(*ec2.CreateLaunchTemplateInput) + // default tags should be included in the LaunchTemplate specification + Expect(*createLaunchTemplateInput.TagSpecifications[0].ResourceType).To(Equal(ec2.ResourceTypeLaunchTemplate)) + ExpectTags(createLaunchTemplateInput.TagSpecifications[0].Tags, defaultTags) }) It("should default to a generated launch template", func() { @@ -533,6 +568,26 @@ var _ = Describe("Allocation", func() { Expect(*launchTemplate.Version).To(Equal("$Latest")) }) }) + Context("Fleets", func() { + It("should have default tags applied", func() { + // default tags applied to all created resources + defaultTags := map[string]string{ + v1alpha5.ProvisionerNameLabelKey: provisioner.Name, + fmt.Sprintf("karpenter.sh/cluster/%s", opts.ClusterName): "owned", + fmt.Sprintf("kubernetes.io/cluster/%s", opts.ClusterName): "owned", + "Name": fmt.Sprintf("karpenter.sh/cluster/%s/provisioner/%s", opts.ClusterName, provisioner.Name), + } + + pod := ExpectProvisioned(ctx, env.Client, selectionController, provisioners, ProvisionerWithProvider(provisioner, provider), test.UnschedulablePod())[0] + ExpectScheduled(ctx, env.Client, pod) + Expect(fakeEC2API.CalledWithCreateFleetInput.Cardinality()).To(Equal(1)) + createFleetInput := fakeEC2API.CalledWithCreateFleetInput.Pop().(*ec2.CreateFleetInput) + + // default tags should be included in the fleet tag specifications + Expect(*createFleetInput.TagSpecifications[2].ResourceType).To(Equal(ec2.ResourceTypeFleet)) + ExpectTags(createFleetInput.TagSpecifications[2].Tags, defaultTags) + }) + }) Context("Subnets", func() { It("should default to the cluster's subnets", func() { pod := ExpectProvisioned(ctx, env.Client, selectionController, provisioners, ProvisionerWithProvider(provisioner, provider), test.UnschedulablePod())[0]