Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

K8s unstructured helper? #137

Open
s3rj1k opened this issue Sep 22, 2023 · 6 comments
Open

K8s unstructured helper? #137

s3rj1k opened this issue Sep 22, 2023 · 6 comments

Comments

@s3rj1k
Copy link

s3rj1k commented Sep 22, 2023

I am curious would it be possible to add some simple wrapper support for K8s unstructured, as it would be really great to use gabs with that object natively.

@mihaitodor
Copy link
Contributor

Hey @s3rj1k, I'd need some more details about that, but, skimming through this article, it sounds like you want to create a gabs container from a weakly-decoded JSON. Is that correct? If yes, try this:

package main

import (
	"fmt"

	"github.com/Jeffail/gabs/v2"
)

func main() {
	newEnvs := []interface{}{
		map[string]interface{}{
			"name": "NAMESPACE",
			"valueFrom": map[string]interface{}{
				"fieldRef": map[string]interface{}{
					"fieldPath": "metadata.namespace",
				},
			},
		},
		map[string]interface{}{
			"name": "POD_UID",
			"valueFrom": map[string]interface{}{
				"fieldRef": map[string]interface{}{
					"fieldPath": "metadata.uid",
				},
			},
		},
	}

	obj := gabs.Wrap(newEnvs)
	fmt.Println(obj.Path("*.valueFrom.fieldRef.fieldPath").String())
}

@s3rj1k
Copy link
Author

s3rj1k commented Sep 22, 2023

@mihaitodor hey, thanks for quick response, I just want a helper to convert gabs <-> unstructured

https://github.com/kubernetes/apimachinery/blob/v0.28.2/pkg/apis/meta/v1/unstructured/unstructured.go#L45

Basically unstructured has embedded Object map[string]interface{} where gabs container has interface{}.

The flow would be something like this:

  • unstructured -> gabs.container
  • some gabs magic manipulating data
  • gabs.container -> unstructured

(hopefully with minimal memory allocation)

@mihaitodor
Copy link
Contributor

mihaitodor commented Sep 22, 2023

@s3rj1k Sure, have you tried the .Data() method?

package main

import (
	"fmt"

	"github.com/Jeffail/gabs/v2"
	"github.com/davecgh/go-spew/spew"
)

func main() {
	newEnvs := []interface{}{
		map[string]interface{}{
			"name": "NAMESPACE",
			"valueFrom": map[string]interface{}{
				"fieldRef": map[string]interface{}{
					"fieldPath": "metadata.namespace",
				},
			},
		},
		map[string]interface{}{
			"name": "POD_UID",
			"valueFrom": map[string]interface{}{
				"fieldRef": map[string]interface{}{
					"fieldPath": "metadata.uid",
				},
			},
		},
	}

	obj := gabs.Wrap(newEnvs)
	fmt.Println(obj.Path("*.valueFrom.fieldRef.fieldPath").String())

	spew.Dump(obj.Data())

	obj.SetP(666, "0.valueFrom.fieldRef.fieldPath")

	spew.Dump(obj.Data())
}

PS: You should be able to use type assertions to get the actual type from the interface{} returned by Data() (in the example above, that would be obj.Data().([]interface{})).

@s3rj1k
Copy link
Author

s3rj1k commented Sep 22, 2023

Flow is a bit different, reversed

package main

import (
	"log"

	"github.com/Jeffail/gabs/v2"
	"github.com/davecgh/go-spew/spew"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"sigs.k8s.io/yaml"
)

func main() {
	b := []byte(`
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  namespace: default
spec:
  containers:
  - name: nginx
    image: nginx:latest
`)

	obj := new(unstructured.Unstructured)

	err := yaml.Unmarshal(b, obj)
	if err != nil {
		log.Fatalf("Failed to unmarshal YAML: %v", err)
	}

	container := gabs.Wrap(obj.Object)

	objNew := new(unstructured.Unstructured)
	objNew.SetUnstructuredContent(container.Data().(map[string]interface{}))

	spew.Dump(obj.Object)
	spew.Dump(objNew.Object)
}

so what I am after here is basically

container.Data().(map[string]interface{})

a more streamlined version of this ^^^

@mihaitodor
Copy link
Contributor

Sure, but that's specific to your use case. Nothing wrong with publishing your own gabs wrapper which exposes a method that returns container.Data().(map[string]interface{}), even if it's just some boilerplate.

@s3rj1k
Copy link
Author

s3rj1k commented Sep 23, 2023

Sure, but that's specific to your use case. Nothing wrong with publishing your own gabs wrapper which exposes a method that returns container.Data().(map[string]interface{}), even if it's just some boilerplate.

Yea, I was hoping for method similar to Data but that will return map[string]interface{} by type casting it internally and panic when error occurs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants