List non-suspended cronjobs using kubectl - kubernetes

How to select SUSPEND=False cronjob?
--selector can't be used as suspend is not added in the labels.

By using a JSONPath expression and passing it via the --output=jsonpath= option to kubectl I was able to select only cronjobs which are unsuspended and print their names as follows:
kubectl get cronjob --output=jsonpath='{range .items[?(.spec.suspend==false)]}{.metadata.name}{"\n"}{end}'
In order yo invert the selection you can simply filter on spec.suspend==true instead of false, i.e.:
kubectl get cronjob --output=jsonpath='{range .items[?(.spec.suspend==true)]}{.metadata.name}{"\n"}{end}'
For explicitness you can additionally pass the --no-headers like so, even though the former command already does not print any headers:
kubectl get cronjob --no-headers --output=jsonpath='{range .items[?(.spec.suspend==false)]}{.metadata.name}{"\n"}{end}'
Last but not least you can combine the commands above with Kubernetes selector expressions; for example:
kubectl get cronjob --selector=sometagkey==sometagvalue --no-headers --output=jsonpath='{range .items[?(.spec.suspend==false)]}{.metadata.name}{"\n"}{end}'

you can't select spec.suspend on a kubectl filter.
You could make your own jq filter
(this is just an example and could be a lot cleaner)
k get cronjob --output=json |
jq -c 'select( .items[].spec.suspend == false)' |
jq '.items[] | .metadata.name + " " + .spec.schedule + " "
+ (.spec.suspend|tostring) + " " + .spec.active'
Or if you don't mind a little golang
// Look at https://github.com/kubernetes/client-go/blob/master/examples/out-of-cluster-client-configuration/main.go
// for the other parameters (like using current kubectl context).
func getCronsBySuspend(clientset *kubernetes.Clientset, namespace string) {
cjs, err := clientset.BatchV1().CronJobs(namespace).List(context.TODO(), metav1.ListOptions{})
if err != nil {
panic(err.Error())
}
var c []string
for _, cron := range cjs.Items {
if *cron.Spec.Suspend == false {
c = append(c, cron.Name)
}
}
fmt.Printf("%v", c)
}

Related

kubectl output formatted : looking for a specific column

I'm looking to have a specific column, through my initial kubectl command
kubectl --context oam-ska-yo_jonnylee -n ebzz get -o json ingressroute zz-oamtoto
This give me the json below
{
"apiVersion":"traefik.containo.us/v1alpha1",
"kind":"IngressRoute",
"metadata":{
"annotations":{
"kubectl.kubernetes.io/last-applied-configuration":"{"sum-up"}\n"
},
"creationTimestamp":"2021-02-23T11:17:56Z",
"generation":1,
"labels":{
"instance":"webzz"
},
"managedFields":[
{
"apiVersion":"traefik.containo.us/v1alpha1",
"fieldsType":"FieldsV1",
"fieldsV1":{
"f:metadata":{
"f:annotations":{
".":{
},
"f:kubectl.kubernetes.io/last-applied-configuration":{
}
},
"f:labels":{
".":{
},
"f:instance":{
}
}
},
"f:spec":{
".":{
},
"f:entryPoints":{
},
"f:routes":{
}
}
},
"manager":"kubectl",
"operation":"Update",
"time":"2021-02-23T11:17:56Z"
}
],
"name":"zz-oamtoto",
"namespace":"ebzz",
"resourceVersion":"61112315",
"selfLink":"/apis/traefik.containo.us/v1alpha1/namespaces/ebzz/ingressroutes/zz-oamtoto",
"uid":"42727XXX-dd9e-45e4-9c7d-1225aea125"
},
"spec":{
"entryPoints":[
"http"
],
"routes":[
{
"kind":"Rule",
"match":"Host(`ebzz.acme.com`)",
"middlewares":[
{
"name":"ebzz-ebzz-basicauth"
}
],
"services":[
{
"kind":"Service",
"name":"zz-oamtoto",
"port":1234
}
]
}
]
}
}
What I'm looking at is to find a specific column, the routes one and most of all, one of its specific sub-column
"match":"Host('ebzz.acme.com')"
I tried the command below
kubectl --context oam-ska-yo_jonnylee -n ebzz get -o=custom-columns=svc:.spec.routes.-kind ingressroute zz-oamtoto
Which gives me this:
[map[kind:Rule match:Host(`ebzz.acme.com`) middlewares:[map[name:ebzz-ebzz-basicauth]] services:[map[kind:Service name:zz-oamtoto port:1234]]]]
What i've tried so far
kubectl --context oam-ska-yo_jonnylee -n ebzz get -o=custom-columns=svc:.spec.routes[kind] ingressroute zz-oamtoto
It gives me this
svc
error: invalid array index kind
I've tried this as well
kubectl --context oam-ska-yo_jonnylee -n ebzz get -o=custom-columns=svc:.spec.routes["kind"] ingressroute zz-oamtoto
But it gives me this
svc
error: invalid array index kind
After many trials, this one works
kubectl --context oam-ska-yo_jonnylee -n ebz get -o=custom-columns=.spec.routes[0].match ingressroute zz-oamtoto
The option custom-columns should give you the tuning if you are looking for a column.
For the first column, you are aiming to, you need to put a .spec followed by a dot and the column name, like this .spec.column_name
Once there, the routes column part, in this example, is an array. Therefore you need to put the [], followed by the number and then followed by the subname, here match. it gives you .spec.routes[0].match
Note: I use a svc in my initial kubectly query. It was a mistake, there is no use for that.
If I understood you correctly, you need
kubectl --context oam-ska-yo_jonnylee -n ebz get ingressroute zz-oamtoto --output=jsonpath={.spec.routes.match}
Here you can find more examples: kubectl Cheat Sheet

Go client SDK: check if a Deployment is fully ready

Say I have an in-memory Deployment object, what is the correct way of testing if it is fully ready? (not in the progress of rollout, upgrade or rollback).
I can't comment, so it will have to be an answer.
I don't think there is a right way of doing this, as it depends on a number of variables. Such as what languages you are proficient with etc.
Where I work, we run a kubectl get pods and grep the information that is relevant (in this case if the pod is available (ready) or not. This is all run through bash as part of a startup script:
function not_ready_count() {
kubectl ${1} get pods -o json | jq -r '.items[].status.conditions[].status' | grep False | wc -l | awk '{ print $1 }'
}
function not_running_count() {
kubectl ${1} get pods -o json | jq -r '.items[].status.phase' | grep -v Running | wc -l | awk '{ print $1 }'
}
function wait_until_running_and_ready() {
sleep 2
while [[ "$(not_running_count ${1})" != "0" ]]; do
echo "waiting for $(not_ready_count ${1}) pods to start"
sleep 3
done
while [[ "$(not_ready_count ${1})" != "0" ]]; do
echo "waiting for $(not_ready_count ${1}) status probes to pass"
sleep 3
done
sleep 2
}
Following is my implementation to check if a deployment is Ready using client-go:
package main
import (
"context"
"flag"
"fmt"
"path/filepath"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
)
func main() {
var kubeconfig *string
if home := homedir.HomeDir(); home != "" {
kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
} else {
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
}
flag.Parse()
config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
panic(err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err)
}
deploymentsClient := clientset.AppsV1().Deployments("my-namespace")
deploy, err := deploymentsClient.Get(context.Background(), "my-deploy", metav1.GetOptions{})
if err != nil {
panic(err)
}
if deploy != nil &&
deploy.Spec.Replicas != nil &&
*deploy.Spec.Replicas == deploy.Status.ReadyReplicas {
fmt.Println("Deployment is READY")
} else {
fmt.Println("Deployment is NOT READY")
}
}

Is there a way to annotate a deployconfig with timestamp?

In short, I'm trying to add an annotation with the actual time.
cmd line should like (or not) :
oc annotate --overwrite dc webtest Last_Jmeter_test='timestamp'
Thanks for any advice!
So I've found a way .
node ('master'){
stage("date") {
date = sh(
script: """
date
""",
returnStdout: true
)
echo "${date}"
}
}
this is by using jenkins .
oc annotate --overwrite dc webtest Last_Jmeter_test='${date}'

How can I provision Kubernetes with kops using multi document yaml file?

I've got a multi document yaml file, how can I provision a Kubernetes cluster from this?
Using kops create -f only seems to import the cluster definition, and does not import the instance groups etc which are defined in additional 'documents' with the yaml:
...
masters: private
nodes: private
---
apiVersion: kops/v1alpha2
kind: InstanceGroup
...
According to kops source code, multiple section in one file is supported.
Perhaps you need to check your file for mistakes.
Here is the part responsible for parsing file and creating resources. To make code shorter, I've deleted all the error checks.
For investigation, please see original file:
func RunCreate(f *util.Factory, out io.Writer, c *CreateOptions) error {
clientset, err := f.Clientset()
// Codecs provides access to encoding and decoding for the scheme
codecs := kopscodecs.Codecs //serializer.NewCodecFactory(scheme)
codec := codecs.UniversalDecoder(kopsapi.SchemeGroupVersion)
var clusterName = ""
//var cSpec = false
var sb bytes.Buffer
fmt.Fprintf(&sb, "\n")
for _, f := range c.Filenames {
contents, err := vfs.Context.ReadFile(f)
// TODO: this does not support a JSON array
sections := bytes.Split(contents, []byte("\n---\n"))
for _, section := range sections {
defaults := &schema.GroupVersionKind{
Group: v1alpha1.SchemeGroupVersion.Group,
Version: v1alpha1.SchemeGroupVersion.Version,
}
o, gvk, err := codec.Decode(section, defaults, nil)
switch v := o.(type) {
case *kopsapi.Cluster:
// Adding a PerformAssignments() call here as the user might be trying to use
// the new `-f` feature, with an old cluster definition.
err = cloudup.PerformAssignments(v)
_, err = clientset.CreateCluster(v)
case *kopsapi.InstanceGroup:
clusterName = v.ObjectMeta.Labels[kopsapi.LabelClusterName]
cluster, err := clientset.GetCluster(clusterName)
_, err = clientset.InstanceGroupsFor(cluster).Create(v)
case *kopsapi.SSHCredential:
clusterName = v.ObjectMeta.Labels[kopsapi.LabelClusterName]
cluster, err := clientset.GetCluster(clusterName)
sshCredentialStore, err := clientset.SSHCredentialStore(cluster)
sshKeyArr := []byte(v.Spec.PublicKey)
err = sshCredentialStore.AddSSHPublicKey("admin", sshKeyArr)
default:
glog.V(2).Infof("Type of object was %T", v)
return fmt.Errorf("Unhandled kind %q in %s", gvk, f)
}
}
}
{
// If there is a value in this sb, this should mean that we have something to deploy
// so let's advise the user how to engage the cloud provider and deploy
if sb.String() != "" {
fmt.Fprintf(&sb, "\n")
fmt.Fprintf(&sb, "To deploy these resources, run: kops update cluster %s --yes\n", clusterName)
fmt.Fprintf(&sb, "\n")
}
_, err := out.Write(sb.Bytes())
}
return nil
}
This may not have been possible in the past, but it's possible now.
Here's how I'm currently IaC'ing my kops cluster.
I have 2 files:
devkube.mycompany.com.cluster.kops.yaml
instancegroups.kops.yaml
The 2nd file is a multi-document yaml file like you're requesting.
(with multiple instance.yaml's inside of it separated by ---).
Note: I've successfully been able to combine both of these .yaml files into a single multi-document .yaml file and have it work fine, I just do it this way so I can reuse the instancegroups.yaml on multiple clusters / keep the git repo dry.
I generated the files by using:
Bash# kops get cluster --name devkube.mycompany.com -o yaml > devkube.mycompany.com.cluster.kops.yaml
Bash# kops get ig --name devkube.mycompany.com -o yaml > instancegroups.kops.yaml
Here's how I use these files to provision a kops cluster from git:
export AWS_PROFILE=devkube-kops
export KOPS_STATE_STORE=s3://kops-state-devkube.mycompany.com
clustername="devkube.mycompany.com"
kops replace --name $clustername -f ../kops/qak8s.vibrenthealth.com.cluster.yaml --force
kops replace --name $clustername -f ../kops/instancegroups.yaml --force
kops create secret --name $clustername sshpublickey admin -i ~/.ssh/id_rsa.pub #so the person who provisions the cluster can ssh into the nodes
kops update cluster --name $clustername --yes

kubectl and seeing (cluster)roles assigned to subjects

I can use kubectl to see to which subjects a cluster role is applied, eg:
kubectl get clusterrolebindings system:node --all-namespaces -o json
{
"apiVersion": "rbac.authorization.k8s.io/v1beta1",
"kind": "ClusterRoleBinding",
....
....
"subjects": [
{
"apiGroup": "rbac.authorization.k8s.io",
"kind": "Group",
"name": "system:nodes"
}
]
}
I would like to get this info the other way around, eg: I want to list all policies applied to the "system:nodes" subject.
How can I do that?
There is no API for the reverse index. You can look up bindings and filter on ones containing the expected subject. For example, using bash, jq, and kubectl:
# $1 is kind (User, Group, ServiceAccount)
# $2 is name ("system:nodes", etc)
# $3 is namespace (optional, only applies to kind=ServiceAccount)
function getRoles() {
local kind="${1}"
local name="${2}"
local namespace="${3:-}"
kubectl get clusterrolebinding -o json | jq -r "
.items[]
|
select(
.subjects[]?
|
select(
.kind == \"${kind}\"
and
.name == \"${name}\"
and
(if .namespace then .namespace else \"\" end) == \"${namespace}\"
)
)
|
(.roleRef.kind + \"/\" + .roleRef.name)
"
}
$ getRoles Group system:authenticated
ClusterRole/system:basic-user
ClusterRole/system:discovery
$ getRoles ServiceAccount attachdetach-controller kube-system
ClusterRole/system:controller:attachdetach-controller