Skip to content

Commit

Permalink
fix: unspecified namespace failure for k8s resources (#768)
Browse files Browse the repository at this point in the history
  • Loading branch information
liu-hm19 authored Feb 20, 2024
1 parent ab28e79 commit 07e76d4
Showing 1 changed file with 40 additions and 4 deletions.
44 changes: 40 additions & 4 deletions pkg/engine/runtime/kubernetes/kubernetes_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package kubernetes
import (
"context"
"errors"
"fmt"
"strings"

jsonpatch "github.com/evanphx/json-patch"
yamlv2 "gopkg.in/yaml.v2"
Expand Down Expand Up @@ -422,7 +424,7 @@ func (k *KubernetesRuntime) buildKubernetesResourceByState(resourceState *apiv1.
// Get resource by unstructured
var resource dynamic.ResourceInterface

resource, err = buildDynamicResource(k.client, k.mapper, gvk, obj.GetNamespace())
resource, err = buildDynamicResource(k.client, k.mapper, gvk, resourceState.ID, obj.GetNamespace())
if err != nil {
return nil, nil, err
}
Expand All @@ -433,17 +435,31 @@ func (k *KubernetesRuntime) buildKubernetesResourceByState(resourceState *apiv1.
// buildDynamicResource get resource interface by gvk and namespace
func buildDynamicResource(
dyn dynamic.Interface, mapper meta.RESTMapper,
gvk *schema.GroupVersionKind, namespace string,
gvk *schema.GroupVersionKind, id, namespace string,
) (dynamic.ResourceInterface, error) {
// Find GVR
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
if err != nil {
return nil, err
}

// validate whether the intent resource id matched with the GVK
if err = validateResourceID(id, gvk); err != nil {
return nil, err
}

// Obtain REST interface for the GVR
var dr dynamic.ResourceInterface
if mapping.Scope.Name() == meta.RESTScopeNameNamespace {
// patch the `default` namespace for namespaced resources without explicitly
// spcified namespace field
keys := strings.Split(id, engine.Separator)
if (len(keys) < 3 || keys[2] == "" || keys[2] == "default") && namespace == "" {
namespace = "default"
} else if len(keys) > 2 && keys[2] != namespace {
return nil, fmt.Errorf("unmatched namespace in resource id: %s and object attribute: %s", keys[2], namespace)
}

// namespaced resources should specify the namespace
dr = dyn.Resource(mapping.Resource).Namespace(namespace)
} else {
Expand Down Expand Up @@ -472,9 +488,9 @@ func (k *KubernetesRuntime) WatchBySelector(
ctx context.Context,
o *unstructured.Unstructured,
gvk schema.GroupVersionKind,
labelStr string,
id, labelStr string,
) (<-chan k8swatch.Event, error) {
clientForResource, err := buildDynamicResource(k.client, k.mapper, &gvk, o.GetNamespace())
clientForResource, err := buildDynamicResource(k.client, k.mapper, &gvk, id, o.GetNamespace())
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -637,3 +653,23 @@ func getNamedGVK(gvk schema.GroupVersionKind) schema.GroupVersionKind {
return schema.GroupVersionKind{}
}
}

func validateResourceID(id string, gvk *schema.GroupVersionKind) error {
keys := strings.Split(id, engine.Separator)
if len(keys) < 2 {
return fmt.Errorf("invalid resource id with missing required fields: %s", id)
}

apiVersion := keys[0]
kind := keys[1]

if apiVersion != gvk.GroupVersion().String() {
return fmt.Errorf("unmatched API Version in resource id: %s and gvk: %s", apiVersion, gvk.GroupVersion().String())
}

if kind != gvk.Kind {
return fmt.Errorf("unmatched Kind in resource id: %s and gvk: %s", kind, gvk.Kind)
}

return nil
}

0 comments on commit 07e76d4

Please sign in to comment.