Skip to content

Commit

Permalink
Merge pull request GoogleCloudPlatform#3460 from nb-goog/config_identity
Browse files Browse the repository at this point in the history
Add AutokeyConfigIdentity
  • Loading branch information
google-oss-prow[bot] authored Jan 8, 2025
2 parents c58ff17 + 605dd21 commit 01f3f16
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 105 deletions.
80 changes: 80 additions & 0 deletions apis/kms/v1beta1/autokeyconfig_identity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
// Copyright 2024 Google LLC
//
// 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 v1beta1

import (
"context"
"fmt"
"strings"

"github.com/GoogleCloudPlatform/k8s-config-connector/apis/common"
refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type KMSAutokeyConfigIdentity struct {
parent *KMSAutokeyConfigParent
}

func (i *KMSAutokeyConfigIdentity) String() string {
return i.parent.String() + "/autokeyConfig"
}

func (r *KMSAutokeyConfigIdentity) Parent() *KMSAutokeyConfigParent {
return r.parent
}

type KMSAutokeyConfigParent struct {
FolderID string
}

func (p *KMSAutokeyConfigParent) String() string {
return "folders/" + p.FolderID
}

func NewAutokeyConfigIdentity(ctx context.Context, reader client.Reader, obj *KMSAutokeyConfig) (*KMSAutokeyConfigIdentity, error) {
// Get Parent
folderRef, err := refsv1beta1.ResolveFolder(ctx, reader, obj, obj.Spec.FolderRef)

if err != nil {
return nil, err
}
folderID := folderRef.FolderID
externalRef := common.ValueOf(obj.Status.ExternalRef)
if externalRef != "" {
actualIdentity, err := ParseKMSAutokeyConfigExternal(externalRef)
if err != nil {
return nil, err
}
if actualIdentity.parent.FolderID != folderID {
return nil, fmt.Errorf("spec.folderRef changed, expect %s, got %s", actualIdentity.parent.FolderID, folderID)
}
}

return &KMSAutokeyConfigIdentity{
parent: &KMSAutokeyConfigParent{FolderID: folderID},
}, nil
}

func ParseKMSAutokeyConfigExternal(external string) (parent *KMSAutokeyConfigIdentity, err error) {
external = strings.TrimPrefix(external, "/")
tokens := strings.Split(external, "/")
if len(tokens) != 3 || tokens[0] != "folders" || tokens[2] != "autokeyConfig" {
return nil, fmt.Errorf("format of KMSAutokeyConfig external=%q was not known (use folders/<folderID>/autokeyConfig)", external)
}
return &KMSAutokeyConfigIdentity{parent: &KMSAutokeyConfigParent{
FolderID: tokens[1],
}}, nil
}
76 changes: 0 additions & 76 deletions apis/kms/v1beta1/autokeyconfig_reference.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ package v1beta1
import (
"context"
"fmt"
"strings"

refsv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
Expand All @@ -41,8 +40,6 @@ type KMSAutokeyConfigRef struct {

// The namespace of a KMSAutokeyConfig resource.
Namespace string `json:"namespace,omitempty"`

parent *KMSAutokeyConfigParent
}

// NormalizedExternal provision the "External" value for other resource that depends on KMSAutokeyConfig.
Expand Down Expand Up @@ -85,79 +82,6 @@ func (r *KMSAutokeyConfigRef) NormalizedExternal(ctx context.Context, reader cli
return r.External, nil
}

// New builds a KMSAutokeyConfigRef from the Config Connector KMSAutokeyConfig object.
func NewKMSAutokeyConfigRef(ctx context.Context, reader client.Reader, obj *KMSAutokeyConfig) (*KMSAutokeyConfigRef, error) {
id := &KMSAutokeyConfigRef{}

// Get Parent
folderRef, err := refsv1beta1.ResolveFolder(ctx, reader, obj, obj.Spec.FolderRef)
if err != nil {
return nil, err
}
folderID := folderRef.FolderID
if folderID == "" {
return nil, fmt.Errorf("cannot resolve project")
}
id.parent = &KMSAutokeyConfigParent{FolderID: folderID}

// Use approved External
externalRef := valueOf(obj.Status.ExternalRef)
if externalRef == "" {
id.External = AsKMSAutokeyConfigExternal(id.parent)
return id, nil
}

// Validate desired with actual
actualParent, err := ParseKMSAutokeyConfigExternal(externalRef)
if err != nil {
return nil, err
}
if actualParent.FolderID != folderID {
return nil, fmt.Errorf("spec.folderRef changed, expect %s, got %s", actualParent.FolderID, folderID)
}
id.External = externalRef
id.parent = &KMSAutokeyConfigParent{FolderID: folderID}
return id, nil
}

func (r *KMSAutokeyConfigRef) Parent() (*KMSAutokeyConfigParent, error) {
if r.parent != nil {
return r.parent, nil
}
if r.External != "" {
parent, err := ParseKMSAutokeyConfigExternal(r.External)
if err != nil {
return nil, err
}
return parent, nil
}
return nil, fmt.Errorf("KMSAutokeyConfigRef not initialized from `NewKMSAutokeyConfigRef` or `NormalizedExternal`")
}

type KMSAutokeyConfigParent struct {
FolderID string
}

func (p *KMSAutokeyConfigParent) String() string {
return "folders/" + p.FolderID
}

func AsKMSAutokeyConfigExternal(parent *KMSAutokeyConfigParent) (external string) {
return parent.String() + "/autokeyConfig"
}

func ParseKMSAutokeyConfigExternal(external string) (parent *KMSAutokeyConfigParent, err error) {
external = strings.TrimPrefix(external, "/")
tokens := strings.Split(external, "/")
if len(tokens) != 3 || tokens[0] != "folders" || tokens[2] != "autokeyConfig" {
return nil, fmt.Errorf("format of KMSAutokeyConfig external=%q was not known (use folders/<folderID>/autokeyConfig)", external)
}
parent = &KMSAutokeyConfigParent{
FolderID: tokens[1],
}
return parent, nil
}

func valueOf[T any](t *T) T {
var zeroVal T
if t == nil {
Expand Down
25 changes: 20 additions & 5 deletions apis/kms/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

34 changes: 16 additions & 18 deletions pkg/controller/direct/kms/autokeyconfig/autokeyconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (m *model) AdapterForObject(ctx context.Context, reader client.Reader, u *u
return nil, fmt.Errorf("error converting to %T: %w", obj, err)
}

id, err := krm.NewKMSAutokeyConfigRef(ctx, reader, obj)
id, err := krm.NewAutokeyConfigIdentity(ctx, reader, obj)
if err != nil {
return nil, fmt.Errorf("unable to resolve folder for autokeyConfig name: %s, err: %w", obj.GetName(), err)
}
Expand Down Expand Up @@ -107,7 +107,7 @@ func (m *model) AdapterForURL(ctx context.Context, url string) (directbase.Adapt
}

type Adapter struct {
id *krm.KMSAutokeyConfigRef
id *krm.KMSAutokeyConfigIdentity
desiredKeyProject *refs.Project
gcpClient *gcp.AutokeyAdminClient
desired *krm.KMSAutokeyConfig
Expand All @@ -120,12 +120,12 @@ var _ directbase.Adapter = &Adapter{}
// Else it will return false and error.
func (a *Adapter) Find(ctx context.Context) (bool, error) {
log := klog.FromContext(ctx).WithName(ctrlName)
log.V(2).Info("getting KMSAutokeyConfig", "name", a.id.External)
log.V(2).Info("getting KMSAutokeyConfig", "name", a.id)

req := &kmspb.GetAutokeyConfigRequest{Name: a.id.External}
req := &kmspb.GetAutokeyConfigRequest{Name: a.id.String()}
autokeyconfigpb, err := a.gcpClient.GetAutokeyConfig(ctx, req)
if err != nil {
return false, fmt.Errorf("getting KMSAutokeyConfig %q: %w", a.id.External, err)
return false, fmt.Errorf("getting KMSAutokeyConfig %q: %w", a.id, err)
}

a.actual = autokeyconfigpb
Expand All @@ -141,7 +141,7 @@ func (a *Adapter) Create(ctx context.Context, createOp *directbase.CreateOperati
func (a *Adapter) Update(ctx context.Context, updateOp *directbase.UpdateOperation) error {

log := klog.FromContext(ctx).WithName(ctrlName)
log.V(2).Info("updating AutokeyConfig", "name", a.id.External)
log.V(2).Info("updating AutokeyConfig", "name", a.id)
mapCtx := &direct.MapContext{}

resource := KMSAutokeyConfig_FromFields(mapCtx, a.id, a.desiredKeyProject)
Expand All @@ -159,7 +159,8 @@ func (a *Adapter) Update(ctx context.Context, updateOp *directbase.UpdateOperati
if mapCtx.Err() != nil {
return mapCtx.Err()
}
status.ExternalRef = &a.id.External
externalRef := a.id.String()
status.ExternalRef = &externalRef
return updateOp.UpdateStatus(ctx, status, nil)
}

Expand All @@ -168,7 +169,7 @@ func (a *Adapter) updateAutokeyConfig(ctx context.Context, resource *kmspb.Autok
// To populate a.actual calling a.Find()
isExist, err := a.Find(ctx)
if !isExist {
return nil, fmt.Errorf("updateAutokeyConfig failed as AutokeyConfig does not exist, name: %s", a.id.External)
return nil, fmt.Errorf("updateAutokeyConfig failed as AutokeyConfig does not exist, name: %s", a.id)
}
if err != nil {
return nil, err
Expand All @@ -179,7 +180,7 @@ func (a *Adapter) updateAutokeyConfig(ctx context.Context, resource *kmspb.Autok
}

if len(updateMask.Paths) == 0 {
log.V(2).Info("no field needs update", "name", a.id.External)
log.V(2).Info("no field needs update", "name", a.id)
return nil, nil
}
req := &kmspb.UpdateAutokeyConfigRequest{
Expand All @@ -188,9 +189,9 @@ func (a *Adapter) updateAutokeyConfig(ctx context.Context, resource *kmspb.Autok
}
updated, err := a.gcpClient.UpdateAutokeyConfig(ctx, req)
if err != nil {
return nil, fmt.Errorf("updating AutokeyConfig %s: %w", a.id.External, err)
return nil, fmt.Errorf("updating AutokeyConfig %s: %w", a.id, err)
}
log.V(2).Info("successfully updated AutokeyConfig", "name", a.id.External)
log.V(2).Info("successfully updated AutokeyConfig", "name", a.id)
return updated, nil
}

Expand All @@ -206,10 +207,7 @@ func (a *Adapter) Export(ctx context.Context) (*unstructured.Unstructured, error
if mapCtx.Err() != nil {
return nil, mapCtx.Err()
}
parent, err := a.id.Parent()
if err != nil {
return nil, err
}
parent := a.id.Parent()
obj.Spec.FolderRef = &refs.FolderRef{External: parent.FolderID}
uObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
if err != nil {
Expand All @@ -226,7 +224,7 @@ func (a *Adapter) Export(ctx context.Context) (*unstructured.Unstructured, error
// Because of the above decision we will update the observedstate for AutokeyConfig with state = UNINITIALIZED
func (a *Adapter) Delete(ctx context.Context, deleteOp *directbase.DeleteOperation) (bool, error) {
log := klog.FromContext(ctx).WithName(ctrlName)
log.V(2).Info("deleting AutokeyConfig", "name", a.id.External)
log.V(2).Info("deleting AutokeyConfig", "name", a.id)
_, err := a.Find(ctx)
if err != nil {
return false, err
Expand All @@ -237,9 +235,9 @@ func (a *Adapter) Delete(ctx context.Context, deleteOp *directbase.DeleteOperati
resource := AutokeyConfig_ToProto(mapCtx, tempKrmAutokeyResource)
updated, err := a.updateAutokeyConfig(ctx, resource)
if err != nil {
return false, fmt.Errorf("updating AutokeyConfig %s: %w", a.id.External, err)
return false, fmt.Errorf("updating AutokeyConfig %s: %w", a.id, err)
}
log.V(2).Info("successfully deleted AutokeyConfig in KCC by resetting the key_project", "name", a.id.External)
log.V(2).Info("successfully deleted AutokeyConfig in KCC by resetting the key_project", "name", a.id)
status := &krm.KMSAutokeyConfigStatus{}
// The state in ObservedState is expected to be UNINITIALIZED as we have set the key_project to empty
status.ObservedState = KMSAutokeyConfigObservedState_FromProto(mapCtx, updated)
Expand Down
8 changes: 2 additions & 6 deletions pkg/controller/direct/kms/autokeyconfig/mapper.generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 01f3f16

Please sign in to comment.