-
Notifications
You must be signed in to change notification settings - Fork 2.9k
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
Support for parsing K8s yaml spec into client-go data structures #193
Comments
@newtonkishore consider converting from YAML to JSON and then unmarshaling into structs as the |
Or actually I'm not sure, I saw something in the issue description of #194 which looks like there's a universal decoder you can use. |
@newtonkishore you can use |
Follow up to this question, what is the right decoder to use if the type of the k8sStruct is not known before decoding? |
|
Yes, there is already code laying around that does this and possibly a few
other necessary things. I'd be a bit surprised if it's not included in the
client library; if not, we can move it.
…On Tue, Nov 7, 2017 at 8:57 AM, Christian Hüning ***@***.***> wrote:
yaml.NewYAMLOrJSONDecoder() etc. has been moved to
k8s.io/apimachinery/pkg/util/yaml
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#193 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAnglqdo5YO9PkNlFPTGrO8GfqKaxsgkks5s0IwGgaJpZM4NahN8>
.
|
@kenontech @ahmetb @newtonkishore @rmohr Here's my solution (thanks to Stefan Schimanski for valuable hints!): import (
"k8s.io/client-go/pkg/api"
_ "k8s.io/client-go/pkg/api/install"
_ "k8s.io/client-go/pkg/apis/extensions/install"
_ "k8s.io/client-go/pkg/apis/rbac/install"
//...
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/apis/rbac/v1beta1"
// make sure to import all client-go/pkg/api(s) you need to cover with your code
)
func someFunc() {
// yamlFiles is an []string
for _, f := range yamlFiles {
decode := api.Codecs.UniversalDeserializer().Decode
obj, groupVersionKind, err := decode([]byte(f), nil, nil)
if err != nil {
log.Fatal(fmt.Sprintf("Error while decoding YAML object. Err was: %s", err))
}
// now use switch over the type of the object
// and match each type-case
switch o := obj.(type) {
case *v1.Pod:
// o is a pod
case *v1beta1.Role:
// o is the actual role Object with all fields etc
case *v1beta1.RoleBinding:
case *v1beta1.ClusterRole:
case *v1beta1.ClusterRoleBinding:
case *v1.ServiceAccount:
default:
//o is unknown for us
}
}
} |
Why my I use |
You are at a different version of the client, in which that code has moved
to the `k8s.io/api/...` package.
…On Thu, Nov 9, 2017 at 3:53 PM, MofeLee ***@***.***> wrote:
@christianhuening <https://github.com/christianhuening>
[image: image]
<https://user-images.githubusercontent.com/5069410/32635653-cd7eaeb2-c576-11e7-9bac-b86cc724c79c.png>
[image: image]
<https://user-images.githubusercontent.com/5069410/32635545-5b54cf92-c576-11e7-91b2-9650571b333e.png>
Why my client-go doesn't have api inside pkg folder?
I use go get k8s.io/client-go/... to get client-go
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#193 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAnglnhOQxMGBNsQqGM0_2flv4CUM23Gks5s05B3gaJpZM4NahN8>
.
|
@lavalamp Thanks! |
For future reference, if you don't have have
|
I am trying a similar thing and am completely lost. What packages are moved to where? I've read the My goal is to read a yaml file with a list of rolebindings into a client-go structure, and there seem to be no possibility to do so, and no documentation at all. I've asked on the Slack channel and nobody could help there. There are some SO questions, but none have an answer to how to work with multiple items in a list in a yaml file. e.g.: https://stackoverflow.com/questions/44306554/how-to-deserialize-kubernetes-yaml-file. My yaml file looks like this apiVersion: v1
kind: List
items:
# --- # Full cluster admin
- kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: ***
labels:
source: ***
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: User
name: ***
apiGroup: rbac.authorization.k8s.io
... This can be used perfectly with |
@mhindery #193 (comment) doesn't work anymore? |
The packages have changes. The codec to use is https://github.com/kubernetes/client-go/blob/master/kubernetes/scheme/register.go#L55. But otherwise, not much has changed. |
While I can read the file using the method above, I never get into the case in the switch with the correct type. Using this file package main
import (
"fmt"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/client-go/kubernetes/scheme"
)
var filecontent = `
apiVersion: v1
kind: List
items:
- kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: myName
labels:
source: myLabel
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
subjects:
- kind: User
name: my@user.com
apiGroup: rbac.authorization.k8s.io
`
func main() {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, _ := decode([]byte(filecontent), nil, nil)
fmt.Printf("%++v\n\n", obj.GetObjectKind())
fmt.Printf("%++v\n\n", obj)
cbl := obj.(*rbacv1.ClusterRoleBindingList) // This fails
fmt.Printf("%++v\n", cbl)
switch o := obj.(type) {
case *rbacv1.ClusterRoleBindingList:
fmt.Println("correct found") // Never happens
default:
fmt.Println("default case")
_ = o
}
} I get this output:
The object I end up with is of the type In #193 (comment), you seem to immediately end up with the right types in the switch-case, while I have a generic one. I've looked at the linked scheme.Scheme.Conver() function, but that hasn't worked for me. What am I missing? |
@mhindery As your error states your func parseK8sYaml(fileR []byte) []runtime.Object {
acceptedK8sTypes := regexp.MustCompile(`(Role|ClusterRole|RoleBinding|ClusterRoleBinding|ServiceAccount)`)
fileAsString := string(fileR[:])
sepYamlfiles := strings.Split(fileAsString, "---")
retVal := make([]runtime.Object, 0, len(sepYamlfiles))
for _, f := range sepYamlfiles {
if f == "\n" || f == "" {
// ignore empty cases
continue
}
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, groupVersionKind, err := decode([]byte(f), nil, nil)
if err != nil {
log.Println(fmt.Sprintf("Error while decoding YAML object. Err was: %s", err))
continue
}
if !acceptedK8sTypes.MatchString(groupVersionKind.Kind) {
log.Printf("The custom-roles configMap contained K8s object types which are not supported! Skipping object with type: %s", groupVersionKind.Kind)
} else {
retVal = append(retVal, obj)
}
}
return retVal
} |
@christianhuening Thanks for your solution. I am having a hard time to convert the runtime.Object to let's say something like v1.ConfigMap. Any suggestion? |
I have a similar issue to @huydinhle, however, I am trying to convert package main
import (
"fmt"
"k8s.io/api/apps/v1beta1"
"k8s.io/client-go/kubernetes/scheme"
)
var json = `
{
"apiVersion": "extensions/v1beta1",
"kind": "Deployment",
"metadata": null,
"name": "my-nginx",
"replicas": 2,
"spec": null,
"template": {
"metadata": {
"labels": {
"run": "my-nginx"
}
},
"spec": {
"containers": [
{
"image": "nginx",
"name": "my-nginx",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
`
func main() {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(json), nil, nil)
if err != nil {
fmt.Printf("%#v", err)
}
deployment := obj.(*v1beta1.Deployment)
fmt.Printf("%#v\n", deployment)
} I get this error: panic: interface conversion: runtime.Object is *v1beta1.Deployment, not *v1beta1.Deployment My package: main
import:
- package: k8s.io/client-go
version: v6.0.0 The error does not make sense to me since it seems like the type is the same. The conversion from |
I have managed to solve it... the deployment resource is of apiVersion Here is the working code: package main
import (
"fmt"
"k8s.io/api/extensions/v1beta1"
"k8s.io/client-go/kubernetes/scheme"
)
var json = `
{
"apiVersion": "extensions/v1beta1",
"kind": "Deployment",
"metadata": null,
"name": "my-nginx",
"replicas": 2,
"spec": null,
"template": {
"metadata": {
"labels": {
"run": "my-nginx"
}
},
"spec": {
"containers": [
{
"image": "nginx",
"name": "my-nginx",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
`
func main() {
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(json), nil, nil)
if err != nil {
fmt.Printf("%#v", err)
}
deployment := obj.(*v1beta1.Deployment)
fmt.Printf("%#v\n", deployment)
} |
why does
the
Tested on HEAD and version 6 of the If I add a print statement in the like so: I can see the response from the server being:
|
Hi, I'm trying to covert a json to a crd struct in my unittest, using the decoder "scheme.Codecs.UniversalDeserializer().Decode". but got an error |
This happened to me with my own CRD's, you'll need to add the scheme like:
|
I used a nifty YAMLtoJSON package to get this working. Check it out: // yamlBytes contains a []byte of my yaml job spec
// convert the yaml to json
jsonBytes, err := yaml.YAMLToJSON(yamlBytes)
if err != nil {
return v1.Job{}, err
}
// unmarshal the json into the kube struct
var job = v1.Job{}
err = json.Unmarshal(jsonBytes, &job)
if err != nil {
return v1.Job{}, err
}
// job now contains the for the job that was in the YAML! |
Issues go stale after 90d of inactivity. If this issue is safe to close now please do so with Send feedback to sig-testing, kubernetes/test-infra and/or fejta. |
It is really helpful for decoding CRDs or other resource from yaml. |
but If my yaml is kubeconfig.(ns:kube-public cm:cluster-info).I have to use ("k8s.io/client-go/tools/clientcmd")clientcmd.Load. yaml.NewYAMLOrJSONDecoder() etc will get me a error "error unmarshaling JSON: while decoding JSON: json: cannot unmarshal array into Go struct field Config.clusters of type map[string]*api.Cluster" why? 😭 |
Here is some code I found useful to discover the right GroupVersionKind for confirming the source package and formatting my yaml config correctly
` Output In configMap.yaml the apiVersion must = v1 `
` |
if stream contains a custom resource this line: Is possible to create a decoder for every resource known to an actual k8s Cluster with a discovery client?. |
I think you're missing to load the scheme for your CRD. Something like:
where |
I am decoding some yaml that can be everything, like kubectl does lauching apply. |
I think kubectl apply does no magic, basically just sending the json. And the API server knows everything possible since you had to explicitly register the CRDs. The universal decoder actually creates the fitting typed object, using reflect, and returns it as Object. So you have to add the scheme for the decoder to know it. A gereric way might be using |
Bug 1986003: bump(k8s.io/*): v0.22.1
I guess I kept it simple...
It is essentially the same way I integrated kind (kubernetes in docker), containerd, and istio into my project. I went down that path once, using |
|
Yeah, this looks cool, thanks for that :) |
Does anyone know how to decode a series of documents from a single YAML file? I have namespace then stateful set with |
@DiveInto
but still I'm seeing this error
Am I doing something wrong? Founded ...
|
@Arsen-Uulu
|
How to import a custom kind that was created on the fly with a crds?
after sucessfully deployed crds and operator |
Can we get the line number while parsing K8s yaml spec into client-go data structures? |
May I suggest y'all ask in slack or something? This issue is from 2017 and it's not a place where many people are going to be expecting questions
The solution to this is to register the type with the scheme...
All the mechanisms I'm aware of have no way of getting a line number like that at the place where they hit an error |
I find it amusing this pops up every so often over the past 6 years. Yet I wonder: would it make sense to document this some place? |
You know what would make more sense and will make all of this go away? The types just need to add |
Hi,
I am trying to create K8s cluster with spec coming from yaml files. I had to write Yaml equivalent of the same datastructures to convert the spec from yaml to go data structures to start the cluster.
The Kubernetes/client-go data structures are tuned to Json Parsing, can we just add "
yaml:""
" support to client-go datastructures?Or is there a better way to do this?
Thanks.
The text was updated successfully, but these errors were encountered: