Deleting a job with client-go - go

Does anyone have any examples of how to delete k8s jobs using client-go?
I've tried the following which deletes the job but leaves the pods behind:
fg := metav1.DeletePropagationBackground
deleteOptions := metav1.DeleteOptions{PropagationPolicy: &fg}
if err := clientset.BatchV1().Jobs("default").Delete("example-job", &deleteOptions); err != nil {
fmt.Printf(err)
}
I've tried using the DeletePropagationForeground option, but that resulted in nothing being deleted.

Related

How do i programatically determine whether a pod is in crashloopbackoff

Is there a way to determine programatically if a pod is in crashloopbackoff?
I tried the following
pods,err := client.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return err
}
for _, item := range pods.Items {
log.Printf("found pod %v with state %v reason %v and phase %v that started at %v",
item.Name, item.Status.Message, item.Status.Reason, item.Status.Phase, item.CreationTimestamp.Time)
}
However this just prints blank for state and reason, tough it prints the phase.
To clarify I am posting a community wiki answer.
It's hiding in ContainerStateWaiting.Reason:
kubectl get po -o jsonpath='{.items[*].status.containerStatuses[*].state.waiting.reason}'
although be aware that it only intermittently shows up there, since it is an intermittent state of the container; perhaps a more programmatic approach is to examine the restartCount and the Error state
See also this repository.

Helm go sdk install chart from external location

Im using the following code to install chart that is bounded in my source code (eg. in my app/chart/chart1 in my go bin app), Now I need to move the chart to git repository or to artifactory,
My question is how can I install the chart from outside my program?
This is the code I use which works for bundled chart
I use the helm3 loader package which works when I have the chart bundled in my app
chart, err := loader.Load(“chart/chart1”)
https://pkg.go.dev/helm.sh/helm/v3#v3.5.4/pkg/chart/loader
Should I load it somehow with an http call or helm have some built in functionality ? we need some efficient way to handle it
It seems that helm during its upgrade/install commands checks first a couple of different locations which you can see getting called here. The content of that function is here.
And then continues here with loader.Load
You can use something like this for installing nginx chart
myChart, err := loader.Load("https://charts.bitnami.com/bitnami/nginx-8.8.4.tgz")
...
install := action.NewInstall(m.actionConfig)
install.ReleaseName = "my-release"
...
myRelease, err := install.Run(myChart, myValues)
It would be similar to:
helm install my-release https://charts.bitnami.com/bitnami/nginx-8.8.4.tgz
loader.load checks only for files and directories. If you want to use URL helm sdk provides LocateChart method in Install interface. Here is an example:
settings := cli.New()
actionConfig := new(action.Configuration)
if err := actionConfig.Init(settings.RESTClientGetter(), settings.Namespace(), os.Getenv("HELM_DRIVER"), log.Printf); err != nil {
log.Printf("%+v", err)
os.Exit(1)
}
client := action.NewInstall(actionConfig)
chrt_path, err := client.LocateChart("https://github.com/kubernetes/ingress-nginx/releases/download/helm-chart-4.0.6/ingress-nginx-4.0.6.tgz", settings); if err != nil {
panic(err)
}
myChart, err := loader.Load(chrt_path); if err != nil {
panic(err)
}
Then you can simple setup install options and call client.Run method.

No data recover from incluster config with kubernetes/go-client

I made a demo with kubernetes/go-client where i tried to list pods from my cluster.
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
fmt.Fprint(w, "There are d pods in the cluster\n", len(pods.Items))
I created serviceaccount token to assign to the pod where this code is running in.
But when code is executed pods.Items has no pods.
I deployed this pod inside minikube. When I launch some kubectl command for listing pods, this way I can get resources so it is no t permissions problems.
I wonder what is happening and how i can fix it.
Repository https://github.com/srpepperoni/inframanager.git
Image is pushed into: https://hub.docker.com/r/jaimeyh/inframanager
The endpoint I have problems with is this one :
mux.HandleFunc("/getPods", GetPodsFromNamespace)
You need to check if the err on the last line is non-nil.
pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})
OK, there is the problem. pods is forbidden: User "system:serviceaccount:mis-pruebas:sa-prueba-go" cannot list resource "pods" in API group "" at the cluster scope
As the error message indicates, the ServiceAccount does not have permission to list pods at cluster scope. You need to create Role and bind it to the ServiceAccount.
The article Using RBAC Authorization even has a role example for how to create such a role.

unstructured.UnstructuredList caused lots of reflect.go trace

I'm trying to use the unstructured.UnstructuredList to reuse come logic for configmap and secret.
However, after adding the ListAndDeployReferredObject, I started to see tons of trace as Starting reflector *unstructured.Unstructured was added to my log file.
Am I doing something odd or I'm missing some setting for using the unstructured.Unstructured?
Thanks in advance.
func (r *ReconcileSubscription) ListAndDeployReferredObject(instance *appv1alpha1.Subscription, gvk schema.GroupVersionKind, refObj referredObject) error {
insName := instance.GetName()
insNs := instance.GetNamespace()
uObjList := &unstructured.UnstructuredList{}
uObjList.SetGroupVersionKind(gvk)
opts := &client.ListOptions{Namespace: insNs}
err := r.Client.List(context.TODO(), uObjList, opts)
if err != nil && !errors.IsNotFound(err) {
klog.Errorf("Failed to list referred objects with error %v ", err)
return err
}
// other logics...
}
I0326 23:05:58.955589 95169 reflector.go:120] Starting reflector *unstructured.Unstructured (10m0s) from pkg/mod/k8s.io/client-go#v0.0.0-20191016111102-bec269661e48/tools/cache/reflector.go:96
...
I0326 23:15:18.718932 95169 reflector.go:158] Listing and watching *unstructured.Unstructured from pkg/mod/k8s.io/client-go#v0.0.0-20191016111102-bec269661e48/tools/cache/reflector.go:96
I figured out these prints are normal, since we are using the dynamic client on our controller for caches

How to overwrite a symlink in Go?

I would like to overwrite a symlink using Go but I couldn't find how to do it.
If I try to create the symlink and it already exists an error is returned.
My code:
err := os.Symlink(filePath, symlinkPath)
if err != nil {
fmt.Println(err)
}
I guess the symlink must be removed and then created again. Is that right? If so, how can I unlink the symlink?
Just check that symlink exists and delete it before creating new one
if _, err := os.Lstat(symlinkPath); err == nil {
os.Remove(symlinkPath)
}
Note that #Vadyus's answer hides actual filesystem errors while running lstat. For example, if your disk is broken and Lstat fails, you will still run os.Remove and ignore its error (DANGEROUS, unless you like to debug things for hours).
The following snippets checks for file existence and other errors correctly:
if _, err := os.Lstat(symlinkPath); err == nil {
if err := os.Remove(symlinkPath); err != nil {
return fmt.Errorf("failed to unlink: %+v", err)
}
} else if os.IsNotExist(err) {
return fmt.Errorf("failed to check symlink: %+v", err)
}
The other answers here are correct...but there are two small issues:
There is a tiny data race where the new symlink will be created elsewhere before here but after the delete, leaving it in a potentially inconsistent state.
If the program were to die / crash before the symlink is created but after the previous one is deleted, it may again leave things in an inconsistent state.
The more atomic way to handle this is to create a temporary symlink and then rename it over the original:
symlinkPathTmp := symlinkPath + ".tmp"
if err := os.Remove(symlinkPathTmp); err != nil && !os.IsNotExist(err) {
return err
}
if err := os.Symlink(filePath, symlinkPathTmp); err != nil {
return err
}
if err := os.Rename(symlinkPathTmp, symlinkPath); err != nil {
return err
}
There is still a small race between deleting the temporary link and re-creating it, but it won't risk leaving the primarily link in an inconsistent state. Ideally, we would be able to work around that by using a randomized name for the temporary link, but Go's TempFile always creates a new file, so it isn't quite as useful. (You could maybe call TempFile, then delete the file name and re-use the name, which would be riskier but still safer then just appending a constant .tmp suffix.)
Even with that race however, you still gain the atomic-ness where any interruptions won't result in a missing link.
Note that this is dependent on Posix behavior and may not work on Windows (why would you be using symlinks on Windows anyway?), but it's a technique shared by many macOS/Linux tools that need atomic symlink replacements.

Resources