diff --git a/pkg/deploy/lattice/target_group_manager.go b/pkg/deploy/lattice/target_group_manager.go index 1ba0fe60..61d26b05 100644 --- a/pkg/deploy/lattice/target_group_manager.go +++ b/pkg/deploy/lattice/target_group_manager.go @@ -14,6 +14,7 @@ import ( "github.com/aws/aws-application-networking-k8s/pkg/config" model "github.com/aws/aws-application-networking-k8s/pkg/model/lattice" "github.com/aws/aws-application-networking-k8s/pkg/utils/gwlog" + "reflect" ) type TargetGroupManager interface { @@ -117,20 +118,20 @@ func (s *defaultTargetGroupManager) update(ctx context.Context, targetGroup *mod if healthCheckConfig == nil { s.log.Debugf("HealthCheck is empty. Resetting to default settings") - protocolVersion := targetGroup.Spec.ProtocolVersion - healthCheckConfig = s.getDefaultHealthCheckConfig(protocolVersion) + healthCheckConfig = &vpclattice.HealthCheckConfig{} } + s.fillDefaultHealthCheckConfig(healthCheckConfig, targetGroup.Spec.ProtocolVersion) - _, err := s.cloud.Lattice().UpdateTargetGroupWithContext(ctx, &vpclattice.UpdateTargetGroupInput{ - HealthCheck: healthCheckConfig, - TargetGroupIdentifier: latticeTg.Id, - }) - - if err != nil { - return model.TargetGroupStatus{}, - fmt.Errorf("Failed UpdateTargetGroup %s due to %w", aws.StringValue(latticeTg.Id), err) + if !reflect.DeepEqual(healthCheckConfig, latticeTg.Config.HealthCheck) { + _, err := s.cloud.Lattice().UpdateTargetGroupWithContext(ctx, &vpclattice.UpdateTargetGroupInput{ + HealthCheck: healthCheckConfig, + TargetGroupIdentifier: latticeTg.Id, + }) + if err != nil { + return model.TargetGroupStatus{}, + fmt.Errorf("Failed UpdateTargetGroup %s due to %w", aws.StringValue(latticeTg.Id), err) + } } - s.log.Infof("Success UpdateTargetGroup %s", aws.StringValue(latticeTg.Id)) modelTgStatus := model.TargetGroupStatus{ Name: aws.StringValue(latticeTg.Name), @@ -356,14 +357,18 @@ func (s *defaultTargetGroupManager) IsTargetGroupMatch(ctx context.Context, // Get default health check configuration according to // https://docs.aws.amazon.com/vpc-lattice/latest/ug/target-group-health-checks.html#health-check-settings func (s *defaultTargetGroupManager) getDefaultHealthCheckConfig(targetGroupProtocolVersion string) *vpclattice.HealthCheckConfig { - var intResetValue int64 = 0 - - defaultMatcher := vpclattice.Matcher{ - HttpCode: aws.String("200"), - } - - defaultPath := "/" - defaultProtocol := vpclattice.TargetGroupProtocolHttp + var ( + defaultHealthCheckIntervalSeconds int64 = 30 + defaultHealthCheckTimeoutSeconds int64 = 5 + defaultHealthyThresholdCount int64 = 5 + defaultUnhealthyThresholdCount int64 = 2 + + defaultMatcher = vpclattice.Matcher{ + HttpCode: aws.String("200"), + } + defaultPath = "/" + defaultProtocol = vpclattice.TargetGroupProtocolHttp + ) if targetGroupProtocolVersion == "" { targetGroupProtocolVersion = vpclattice.TargetGroupProtocolVersionHttp1 @@ -383,9 +388,40 @@ func (s *defaultTargetGroupManager) getDefaultHealthCheckConfig(targetGroupProto Path: &defaultPath, Matcher: &defaultMatcher, Port: nil, // Use target port - HealthCheckIntervalSeconds: &intResetValue, - HealthyThresholdCount: &intResetValue, - UnhealthyThresholdCount: &intResetValue, - HealthCheckTimeoutSeconds: &intResetValue, + HealthyThresholdCount: &defaultHealthyThresholdCount, + UnhealthyThresholdCount: &defaultUnhealthyThresholdCount, + HealthCheckTimeoutSeconds: &defaultHealthCheckTimeoutSeconds, + HealthCheckIntervalSeconds: &defaultHealthCheckIntervalSeconds, + } +} + +func (s *defaultTargetGroupManager) fillDefaultHealthCheckConfig(hc *vpclattice.HealthCheckConfig, targetGroupProtocolVersion string) { + defaultCfg := s.getDefaultHealthCheckConfig(targetGroupProtocolVersion) + if hc.Enabled == nil { + hc.Enabled = defaultCfg.Enabled + } + if hc.Protocol == nil { + hc.Protocol = defaultCfg.Protocol + } + if hc.ProtocolVersion == nil { + hc.ProtocolVersion = defaultCfg.ProtocolVersion + } + if hc.Path == nil { + hc.Path = defaultCfg.Path + } + if hc.Matcher == nil { + hc.Matcher = defaultCfg.Matcher + } + if hc.HealthCheckTimeoutSeconds == nil { + hc.HealthCheckTimeoutSeconds = defaultCfg.HealthCheckTimeoutSeconds + } + if hc.HealthCheckIntervalSeconds == nil { + hc.HealthCheckIntervalSeconds = defaultCfg.HealthCheckIntervalSeconds + } + if hc.HealthyThresholdCount == nil { + hc.HealthyThresholdCount = defaultCfg.HealthyThresholdCount + } + if hc.UnhealthyThresholdCount == nil { + hc.UnhealthyThresholdCount = defaultCfg.UnhealthyThresholdCount } } diff --git a/pkg/deploy/lattice/target_group_manager_test.go b/pkg/deploy/lattice/target_group_manager_test.go index 80eee329..1408b591 100644 --- a/pkg/deploy/lattice/target_group_manager_test.go +++ b/pkg/deploy/lattice/target_group_manager_test.go @@ -251,6 +251,64 @@ func Test_CreateTargetGroup_TGActive_UpdateHealthCheck(t *testing.T) { } } +func Test_CreateTargetGroup_TGActive_HealthCheckSame(t *testing.T) { + ctx := context.TODO() + c := gomock.NewController(t) + defer c.Finish() + + mockLattice := mocks.NewMockLattice(c) + mockTagging := mocks.NewMockTagging(c) + cloud := pkg_aws.NewDefaultCloudWithTagging(mockLattice, mockTagging, TestCloudConfig) + + hcConfig := &vpclattice.HealthCheckConfig{ + Enabled: aws.Bool(true), + HealthCheckIntervalSeconds: aws.Int64(3), + HealthCheckTimeoutSeconds: aws.Int64(3), + HealthyThresholdCount: aws.Int64(3), + Matcher: &vpclattice.Matcher{HttpCode: aws.String("200")}, + Path: aws.String("/"), + Port: nil, + Protocol: aws.String(vpclattice.TargetGroupProtocolHttps), + ProtocolVersion: aws.String(vpclattice.TargetGroupProtocolVersionHttp1), + UnhealthyThresholdCount: aws.Int64(3), + } + tgSpec := model.TargetGroupSpec{ + Port: 80, + Protocol: vpclattice.TargetGroupProtocolHttps, + ProtocolVersion: vpclattice.TargetGroupProtocolVersionHttp1, + HealthCheckConfig: hcConfig, + } + + tgCreateInput := model.TargetGroup{ + ResourceMeta: core.ResourceMeta{}, + Spec: tgSpec, + } + + tgOutput := vpclattice.GetTargetGroupOutput{ + Arn: aws.String("arn"), + Id: aws.String("id"), + Name: aws.String("test-https-http1"), + Status: aws.String(vpclattice.TargetGroupStatusActive), + Config: &vpclattice.TargetGroupConfig{ + Port: aws.Int64(80), + HealthCheck: hcConfig, + Protocol: aws.String(vpclattice.TargetGroupProtocolHttps), + ProtocolVersion: aws.String(vpclattice.TargetGroupProtocolVersionHttp1), + }, + } + + mockTagging.EXPECT().FindResourcesByTags(ctx, gomock.Any(), gomock.Any()).Return([]string{"arn"}, nil) + mockLattice.EXPECT().GetTargetGroupWithContext(ctx, gomock.Any()).Return(&tgOutput, nil) + mockLattice.EXPECT().UpdateTargetGroupWithContext(ctx, gomock.Any()).Times(0) + + tgManager := NewTargetGroupManager(gwlog.FallbackLogger, cloud) + resp, err := tgManager.Upsert(ctx, &tgCreateInput) + + assert.Nil(t, err) + assert.Equal(t, "arn", resp.Arn) + assert.Equal(t, "id", resp.Id) +} + // target group status is create-in-progress before creation, return Retry func Test_CreateTargetGroup_ExistingTG_Status_Retry(t *testing.T) { c := gomock.NewController(t) @@ -782,12 +840,15 @@ func Test_ListTG_NoTG(t *testing.T) { func Test_defaultTargetGroupManager_getDefaultHealthCheckConfig(t *testing.T) { var ( - resetValue = aws.Int64(0) defaultMatcher = &vpclattice.Matcher{ HttpCode: aws.String("200"), } - defaultPath = aws.String("/") - defaultProtocol = aws.String(vpclattice.TargetGroupProtocolHttp) + defaultPath = aws.String("/") + defaultProtocol = aws.String(vpclattice.TargetGroupProtocolHttp) + defaultHealthCheckIntervalSeconds = aws.Int64(30) + defaultHealthCheckTimeoutSeconds = aws.Int64(5) + defaultHealthyThresholdCount = aws.Int64(5) + defaultUnhealthyThresholdCount = aws.Int64(2) ) type args struct { @@ -806,10 +867,10 @@ func Test_defaultTargetGroupManager_getDefaultHealthCheckConfig(t *testing.T) { }, want: &vpclattice.HealthCheckConfig{ Enabled: aws.Bool(true), - HealthCheckIntervalSeconds: resetValue, - HealthCheckTimeoutSeconds: resetValue, - HealthyThresholdCount: resetValue, - UnhealthyThresholdCount: resetValue, + HealthCheckIntervalSeconds: defaultHealthCheckIntervalSeconds, + HealthCheckTimeoutSeconds: defaultHealthCheckTimeoutSeconds, + HealthyThresholdCount: defaultHealthyThresholdCount, + UnhealthyThresholdCount: defaultUnhealthyThresholdCount, Matcher: defaultMatcher, Path: defaultPath, Port: nil, @@ -824,10 +885,10 @@ func Test_defaultTargetGroupManager_getDefaultHealthCheckConfig(t *testing.T) { }, want: &vpclattice.HealthCheckConfig{ Enabled: aws.Bool(true), - HealthCheckIntervalSeconds: resetValue, - HealthCheckTimeoutSeconds: resetValue, - HealthyThresholdCount: resetValue, - UnhealthyThresholdCount: resetValue, + HealthCheckIntervalSeconds: defaultHealthCheckIntervalSeconds, + HealthCheckTimeoutSeconds: defaultHealthCheckTimeoutSeconds, + HealthyThresholdCount: defaultHealthyThresholdCount, + UnhealthyThresholdCount: defaultUnhealthyThresholdCount, Matcher: defaultMatcher, Path: defaultPath, Port: nil, @@ -842,10 +903,10 @@ func Test_defaultTargetGroupManager_getDefaultHealthCheckConfig(t *testing.T) { }, want: &vpclattice.HealthCheckConfig{ Enabled: aws.Bool(false), - HealthCheckIntervalSeconds: resetValue, - HealthCheckTimeoutSeconds: resetValue, - HealthyThresholdCount: resetValue, - UnhealthyThresholdCount: resetValue, + HealthCheckIntervalSeconds: defaultHealthCheckIntervalSeconds, + HealthCheckTimeoutSeconds: defaultHealthCheckTimeoutSeconds, + HealthyThresholdCount: defaultHealthyThresholdCount, + UnhealthyThresholdCount: defaultUnhealthyThresholdCount, Matcher: defaultMatcher, Path: defaultPath, Port: nil, @@ -860,10 +921,10 @@ func Test_defaultTargetGroupManager_getDefaultHealthCheckConfig(t *testing.T) { }, want: &vpclattice.HealthCheckConfig{ Enabled: aws.Bool(false), - HealthCheckIntervalSeconds: resetValue, - HealthCheckTimeoutSeconds: resetValue, - HealthyThresholdCount: resetValue, - UnhealthyThresholdCount: resetValue, + HealthCheckIntervalSeconds: defaultHealthCheckIntervalSeconds, + HealthCheckTimeoutSeconds: defaultHealthCheckTimeoutSeconds, + HealthyThresholdCount: defaultHealthyThresholdCount, + UnhealthyThresholdCount: defaultUnhealthyThresholdCount, Matcher: defaultMatcher, Path: defaultPath, Port: nil,