diff --git a/controller/konnect/ops/kongcertificate.go b/controller/konnect/ops/kongcertificate.go index 3e5fa2cfe..0392a8c70 100644 --- a/controller/konnect/ops/kongcertificate.go +++ b/controller/konnect/ops/kongcertificate.go @@ -12,4 +12,5 @@ type CertificatesSDK interface { CreateCertificate(ctx context.Context, controlPlaneID string, certificate sdkkonnectcomp.CertificateInput, opts ...sdkkonnectops.Option) (*sdkkonnectops.CreateCertificateResponse, error) UpsertCertificate(ctx context.Context, request sdkkonnectops.UpsertCertificateRequest, opts ...sdkkonnectops.Option) (*sdkkonnectops.UpsertCertificateResponse, error) DeleteCertificate(ctx context.Context, controlPlaneID string, certificateID string, opts ...sdkkonnectops.Option) (*sdkkonnectops.DeleteCertificateResponse, error) + ListCertificate(ctx context.Context, request sdkkonnectops.ListCertificateRequest, opts ...sdkkonnectops.Option) (*sdkkonnectops.ListCertificateResponse, error) } diff --git a/controller/konnect/ops/kongcertificate_mock.go b/controller/konnect/ops/kongcertificate_mock.go index 4751e0227..1b5d2f4ae 100644 --- a/controller/konnect/ops/kongcertificate_mock.go +++ b/controller/konnect/ops/kongcertificate_mock.go @@ -175,6 +175,80 @@ func (_c *MockCertificatesSDK_DeleteCertificate_Call) RunAndReturn(run func(cont return _c } +// ListCertificate provides a mock function with given fields: ctx, request, opts +func (_m *MockCertificatesSDK) ListCertificate(ctx context.Context, request operations.ListCertificateRequest, opts ...operations.Option) (*operations.ListCertificateResponse, error) { + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, request) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ListCertificate") + } + + var r0 *operations.ListCertificateResponse + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, operations.ListCertificateRequest, ...operations.Option) (*operations.ListCertificateResponse, error)); ok { + return rf(ctx, request, opts...) + } + if rf, ok := ret.Get(0).(func(context.Context, operations.ListCertificateRequest, ...operations.Option) *operations.ListCertificateResponse); ok { + r0 = rf(ctx, request, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*operations.ListCertificateResponse) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, operations.ListCertificateRequest, ...operations.Option) error); ok { + r1 = rf(ctx, request, opts...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MockCertificatesSDK_ListCertificate_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListCertificate' +type MockCertificatesSDK_ListCertificate_Call struct { + *mock.Call +} + +// ListCertificate is a helper method to define mock.On call +// - ctx context.Context +// - request operations.ListCertificateRequest +// - opts ...operations.Option +func (_e *MockCertificatesSDK_Expecter) ListCertificate(ctx interface{}, request interface{}, opts ...interface{}) *MockCertificatesSDK_ListCertificate_Call { + return &MockCertificatesSDK_ListCertificate_Call{Call: _e.mock.On("ListCertificate", + append([]interface{}{ctx, request}, opts...)...)} +} + +func (_c *MockCertificatesSDK_ListCertificate_Call) Run(run func(ctx context.Context, request operations.ListCertificateRequest, opts ...operations.Option)) *MockCertificatesSDK_ListCertificate_Call { + _c.Call.Run(func(args mock.Arguments) { + variadicArgs := make([]operations.Option, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(operations.Option) + } + } + run(args[0].(context.Context), args[1].(operations.ListCertificateRequest), variadicArgs...) + }) + return _c +} + +func (_c *MockCertificatesSDK_ListCertificate_Call) Return(_a0 *operations.ListCertificateResponse, _a1 error) *MockCertificatesSDK_ListCertificate_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MockCertificatesSDK_ListCertificate_Call) RunAndReturn(run func(context.Context, operations.ListCertificateRequest, ...operations.Option) (*operations.ListCertificateResponse, error)) *MockCertificatesSDK_ListCertificate_Call { + _c.Call.Return(run) + return _c +} + // UpsertCertificate provides a mock function with given fields: ctx, request, opts func (_m *MockCertificatesSDK) UpsertCertificate(ctx context.Context, request operations.UpsertCertificateRequest, opts ...operations.Option) (*operations.UpsertCertificateResponse, error) { _va := make([]interface{}, len(opts)) diff --git a/controller/konnect/ops/ops.go b/controller/konnect/ops/ops.go index 88f4ea63a..6fcedcec2 100644 --- a/controller/konnect/ops/ops.go +++ b/controller/konnect/ops/ops.go @@ -126,6 +126,8 @@ func Create[ id, err = getKongKeyForUID(ctx, sdk.GetKeysSDK(), ent) case *configurationv1alpha1.KongUpstream: id, err = getKongUpstreamForUID(ctx, sdk.GetUpstreamsSDK(), ent) + case *configurationv1alpha1.KongCertificate: + id, err = getKongCertificateForUID(ctx, sdk.GetCertificatesSDK(), ent) // --------------------------------------------------------------------- // TODO: add other Konnect types default: diff --git a/controller/konnect/ops/ops_kongcertificate.go b/controller/konnect/ops/ops_kongcertificate.go index 489856df1..28c3ac5aa 100644 --- a/controller/konnect/ops/ops_kongcertificate.go +++ b/controller/konnect/ops/ops_kongcertificate.go @@ -3,6 +3,8 @@ package ops import ( "context" "errors" + "fmt" + "github.com/samber/lo" sdkkonnectcomp "github.com/Kong/sdk-konnect-go/models/components" sdkkonnectops "github.com/Kong/sdk-konnect-go/models/operations" @@ -33,12 +35,15 @@ func createCertificate( // Can't adopt it as it will cause conflicts between the controller // that created that entity and already manages it, hm if errWrap := wrapErrIfKonnectOpFailed(err, CreateOp, cert); errWrap != nil { - SetKonnectEntityProgrammedConditionFalse(cert, "FailedToCreate", errWrap.Error()) return errWrap } - cert.Status.Konnect.SetKonnectID(*resp.Certificate.ID) - SetKonnectEntityProgrammedCondition(cert) + if resp == nil || resp.Certificate == nil || resp.Certificate.ID == nil || *resp.Certificate.ID == "" { + return fmt.Errorf("failed creating %s: %w", cert.GetTypeName(), ErrNilResponse) + } + + // At this point, the Certificate has been created successfully. + cert.SetKonnectID(*resp.Certificate.ID) return nil } @@ -89,12 +94,9 @@ func updateCertificate( } } } - SetKonnectEntityProgrammedConditionFalse(cert, "FailedToUpdate", errWrap.Error()) return errWrap } - SetKonnectEntityProgrammedCondition(cert) - return nil } @@ -139,3 +141,23 @@ func kongCertificateToCertificateInput(cert *configurationv1alpha1.KongCertifica Tags: GenerateTagsForObject(cert, cert.Spec.Tags...), } } + +func getKongCertificateForUID( + ctx context.Context, + sdk CertificatesSDK, + cert *configurationv1alpha1.KongCertificate, +) (string, error) { + resp, err := sdk.ListCertificate(ctx, sdkkonnectops.ListCertificateRequest{ + ControlPlaneID: cert.GetControlPlaneID(), + Tags: lo.ToPtr(UIDLabelForObject(cert)), + }) + if err != nil { + return "", fmt.Errorf("failed to list %s: %w", cert.GetTypeName(), err) + } + + if resp == nil || resp.Object == nil { + return "", fmt.Errorf("failed listing %s: %w", cert.GetTypeName(), ErrNilResponse) + } + + return getMatchingEntryFromListResponseData(sliceToEntityWithIDSlice(resp.Object.Data), cert) +}