Skip to content

Instantly share code, notes, and snippets.

@dwmkerr
Last active October 10, 2022 06:06
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save dwmkerr/7332888e092156ce8ce4ea551b0c321f to your computer and use it in GitHub Desktop.
Save dwmkerr/7332888e092156ce8ce4ea551b0c321f to your computer and use it in GitHub Desktop.
Example showing how to patch an Istio VirtualService CRDs Golang
// Example showing how to patch Kubernetes resources.
package main
import (
"encoding/json"
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/dynamic"
_ "k8s.io/client-go/plugin/pkg/client/auth"
"k8s.io/client-go/tools/clientcmd"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
var (
// Leave blank for the default context in your kube config.
context = ""
// Name of the VirtualService to weight, and the two weight values.
virtualServiceName = "service2"
weight1 = uint32(50)
weight2 = uint32(50)
)
// patchStringValue specifies a patch operation for a string.
type patchStringValue struct {
Op string `json:"op"`
Path string `json:"path"`
Value string `json:"value"`
}
// patchStringValue specifies a patch operation for a uint32.
type patchUInt32Value struct {
Op string `json:"op"`
Path string `json:"path"`
Value uint32 `json:"value"`
}
func setVirtualServiceWeights(client dynamic.Interface, virtualServiceName string, weight1 uint32, weight2 uint32) error {
// Create a GVR which represents an Istio Virtual Service.
virtualServiceGVR := schema.GroupVersionResource{
Group: "networking.istio.io",
Version: "v1alpha3",
Resource: "virtualservices",
}
// Weight the two routes - 50/50.
patchPayload := make([]patchUInt32Value, 2)
patchPayload[0].Op = "replace"
patchPayload[0].Path = "/spec/http/0/route/0/weight"
patchPayload[0].Value = 50
patchPayload[1].Op = "replace"
patchPayload[1].Path = "/spec/http/0/route/1/weight"
patchPayload[1].Value = 50
patchBytes, _ := json.Marshal(patchPayload)
// Apply the patch to the 'service2' service.
_, err := client.Resource(virtualServiceGVR).Namespace("default").Patch(virtualServiceName, types.JSONPatchType, patchBytes, metav1.PatchOptions{})
return err
}
func main() {
// Get the local kube config.
fmt.Printf("Connecting to Kubernetes Context %v\n", context)
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
&clientcmd.ConfigOverrides{CurrentContext: context}).ClientConfig()
if err != nil {
panic(err.Error())
}
// Creates the dynamic interface.
dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
panic(err.Error())
}
// Re-balance the weights of the hosts in the virtual service.
setVirtualServiceWeights(dynamicClient, "service2", 50, 50)
}
@eskuai
Copy link

eskuai commented Jun 6, 2019

--# go build
--# tmp/for/tool/work
./k8s-patch-virtualservice.go:57:73: not enough arguments in call to client.Resource(virtualServiceGVR).Namespace("default").Patch
have (string, types.PatchType, []byte)
want (string, types.PatchType, []byte, v1.PatchOptions, ...string)

--- about go version ???

@dwmkerr
Copy link
Author

dwmkerr commented Jun 7, 2019

I think it's the fact that the k8s api is changing regularly - dependency management for golang is a total PITA

@rsreeni
Copy link

rsreeni commented Aug 23, 2019

I see from your example, that you are updating a VirtualService changing the weights.. is there an example for creating a new VirtualService similarly ? Thanks, Sreeni

@dwmkerr
Copy link
Author

dwmkerr commented Aug 26, 2019

You should be able to change the 'Patch' to a 'Post' and that would basically do the job!

@rsreeni
Copy link

rsreeni commented Aug 27, 2019

--# go build
--# tmp/for/tool/work
./k8s-patch-virtualservice.go:57:73: not enough arguments in call to client.Resource(virtualServiceGVR).Namespace("default").Patch
have (string, types.PatchType, []byte)
want (string, types.PatchType, []byte, v1.PatchOptions, ...string)

--- about go version ???

@eskuai, did you solve the issue ? Im using go 1.12 and am getting the same error.

@dwmkerr, Tried replacing Patch with Post and didnt work. I will keep looking .In the mean while any insights into solving the error me and eksuai both got ?

@yehaifeng
Copy link

yehaifeng commented Dec 11, 2019

@rseeni
I add this and OK.
_, err := client.Resource(virtualServiceGVR).Namespace("default").Patch(virtualServiceName, types.JSONPatchType, patchBytes, metav1.PatchOptions{})

First , import metav1
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

@dwmkerr
Copy link
Author

dwmkerr commented Dec 11, 2019

Thanks @yehaifeng! I've updated the gist

@pitiwari
Copy link

now in patch we need to specify the context and context cant be empty. Getting this error now

./vs-crd.go:56:90: not enough arguments in call to client.Resource(virtualServiceGVR).Namespace("flagger-version-affinity").Patch
have (string, types.PatchType, []byte, v1.PatchOptions)
want (context.Context, string, types.PatchType, []byte, v1.PatchOptions, ...string)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment