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

Make event notifications actionable #803

Merged
merged 5 commits into from
Oct 12, 2022

Conversation

pkosiec
Copy link
Member

@pkosiec pkosiec commented Oct 10, 2022

Description

Changes proposed in this pull request:

  • Rework long/short notifications to Block kit for socket Slack (do not use deprecated API anymore)
  • Implement Command Guard which facilitate getting commands for a given resource and verb
  • Make notifications actionable
  • Add empty command response message
  • Add ingresses to default configuration of executor

To do

On this PR:

  • Unit tests
  • Testing instruction

In follow-up PRs:

  • Delete confirmation implementation
  • Telemetry
  • Pass real CommandGuard to kubectl survey
  • Documentation

Testing

Check out this PR and run Botkube locally:

export KUBECONFIG=...

export BOTKUBE_SETTINGS_LOG_LEVEL=info
export BOTKUBE_SETTINGS_KUBECONFIG=$KUBECONFIG
export BOTKUBE_CONFIG_PATHS="$(pwd)/comm_config.yaml"
go run cmd/botkube/main.go

Use the following values (NOTE: test both short and long notifications):

Show
communications:
  'default-group':
    # Settings for Slack
    socketSlack:
      enabled: true
      appToken: "xapp-..."
      botToken: "xoxb-..."
      notification:
        type: "short" # TODO: Change to `short` during testing
      channels:
        'default':
          name: botkube-demo
          bindings:
            executors:
              - kubectl-backend
            sources:
              - k8s-all-events
              - k8s-recommendation-events

settings:
  clusterName: gke-playground
  configWatcher: true
  lifecycleServer:
    deployment:
      name: botkube
      namespace: botkube
    port: "2113"

configWatcher:
  enabled: false
  initialSyncTimeout: 0

executors:
  'kubectl-backend':
    kubectl:
      namespaces:
        include:
          - ".*"
      enabled: true
      commands:
        verbs: [ "run", "api-resources", "api-versions", "cluster-info", "describe", "diff", "explain", "get", "logs", "top", "auth", "delete" ]
        resources: [ "deployments", "pods", "namespaces", "daemonsets", "ingresses", "statefulsets", "storageclasses", "nodes", "configmaps", "services" ]
      defaultNamespace: backend
      restrictAccess: false

rbac:
  create: true
  rules:
    - apiGroups: ["*"]
      resources: ["*"]
      verbs: ["get", "watch", "list"]
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["delete", "create"]

analytics:
  disable: true

# -- Map of sources. Source contains configuration for Kubernetes events and sending recommendations.
# The property name under `sources` object is an alias for a given configuration. You can define multiple sources configuration with different names.
# Key name is used as a binding reference.
# @default -- See the `values.yaml` file for full object.
#
## Format: sources.<alias>
sources:
  'k8s-recommendation-events':
    displayName: "Kubernetes Recommendations"
    # -- Describes Kubernetes source configuration.
    kubernetes:
      # -- Describes configuration for various recommendation insights.
      recommendations:
        # -- Recommendations for Pod Kubernetes resource.
        pod:
          # -- If true, notifies about Pod containers that use `latest` tag for images.
          noLatestImageTag: true
          # -- If true, notifies about Pod resources created without labels.
          labelsSet: true
        # -- Recommendations for Ingress Kubernetes resource.
        ingress:
          # -- If true, notifies about Ingress resources with invalid backend service reference.
          backendServiceValid: true
          # -- If true, notifies about Ingress resources with invalid TLS secret reference.
          tlsSecretValid: true

  'k8s-all-events':
    displayName: "Kubernetes Info"
    # -- Describes Kubernetes source configuration.
    kubernetes:
      # -- Describes namespaces for every Kubernetes resources you want to watch or exclude.
      # These namespaces are applied to every resource specified in the resources list.
      # However, every specified resource can override this by using its own namespaces object.
      namespaces: &k8s-events-namespaces
        # Include contains a list of allowed Namespaces.
        # It can also contain a regex expressions:
        #  `- ".*"` - to specify all Namespaces.
        include:
          - ".*"
        # Exclude contains a list of Namespaces to be ignored even if allowed by Include.
        # It can also contain a regex expressions:
        #  `- "test-.*"` - to specif all Namespaces with `test-` prefix.
        # exclude: []

      # -- Describes events for every Kubernetes resources you want to watch or exclude.
      # These events are applied to every resource specified in the resources list.
      # However, every specified resource can override this by using its own events object.
      events:
        - create
        - delete
        - error

      # -- Describes the Kubernetes resources you want to watch.
      # @default -- See the `values.yaml` file for full object.
      resources:
        - name: v1/pods             # Name of the resource. Resource name must be in group/version/resource (G/V/R) format
          # resource name should be plural (e.g apps/v1/deployments, v1/pods)

        #  namespaces:             # Overrides 'source'.kubernetes.namespaces
        #    include:
        #      - ".*"
        #    exclude: []
        - name: v1/services
        - name: networking.k8s.io/v1/ingresses
        - name: v1/nodes
        - name: v1/namespaces
        - name: v1/persistentvolumes
        - name: v1/persistentvolumeclaims
        - name: v1/configmaps
        - name: rbac.authorization.k8s.io/v1/roles
        - name: rbac.authorization.k8s.io/v1/rolebindings
        - name: rbac.authorization.k8s.io/v1/clusterrolebindings
        - name: rbac.authorization.k8s.io/v1/clusterroles
        - name: apps/v1/daemonsets
          events: # Overrides 'source'.kubernetes.events
            - create
            - update
            - delete
            - error
          updateSetting:
            includeDiff: true
            fields:
              - spec.template.spec.containers[*].image
              - status.numberReady
        - name: batch/v1/jobs
          events: # Overrides 'source'.kubernetes.events
            - create
            - update
            - delete
            - error
          updateSetting:
            includeDiff: true
            fields:
              - spec.template.spec.containers[*].image
              - status.conditions[*].type
        - name: apps/v1/deployments
          events: # Overrides 'source'.kubernetes.events
            - create
            - update
            - delete
            - error
          updateSetting:
            includeDiff: true
            fields:
              - spec.template.spec.containers[*].image
              - status.availableReplicas
        - name: apps/v1/statefulsets
          events: # Overrides 'source'.kubernetes.events
            - create
            - update
            - delete
            - error
          updateSetting:
            includeDiff: true
            fields:
              - spec.template.spec.containers[*].image
              - status.readyReplicas
        ## Custom resource example
        # - name: velero.io/v1/backups
        #   namespaces:
        #     include:
        #       - ".*"
        #     exclude:
        #       -
        #   events:
        #     - create
        #     - update
        #     - delete
        #     - error
        #   updateSetting:
        #     includeDiff: true
        #     fields:
        #       - status.phase

  'k8s-err-events':
    displayName: "Kubernetes Errors"

    # -- Describes Kubernetes source configuration.
    kubernetes:
      # -- Describes namespaces for every Kubernetes resources you want to watch or exclude.
      # These namespaces are applied to every resource specified in the resources list.
      # However, every specified resource can override this by using its own namespaces object.
      namespaces: *k8s-events-namespaces

      # -- Describes events for every Kubernetes resources you want to watch or exclude.
      # These events are applied to every resource specified in the resources list.
      # However, every specified resource can override this by using its own events object.
      events:
        - error

      # -- Describes the Kubernetes resources you want to watch.
      # @default -- See the `values.yaml` file for full object.
      resources:
        - name: v1/pods
        - name: v1/services
        - name: networking.k8s.io/v1/ingresses
        - name: v1/nodes
        - name: v1/namespaces
        - name: v1/persistentvolumes
        - name: v1/persistentvolumeclaims
        - name: v1/configmaps
        - name: rbac.authorization.k8s.io/v1/roles
        - name: rbac.authorization.k8s.io/v1/rolebindings
        - name: rbac.authorization.k8s.io/v1/clusterrolebindings
        - name: rbac.authorization.k8s.io/v1/clusterroles
        - name: apps/v1/deployments
        - name: apps/v1/statefulsets
        - name: apps/v1/daemonsets
        - name: batch/v1/jobs

Trigger some events:

k apply -f ~/file.yaml
k delete -f ~/file.yaml

With the following file:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress
spec:
  rules:
    - host: "foo"
      http:
        paths:
          - path: "/testpath"
            pathType: Exact
            backend:
              service:
                name: "foo"
                port:
                  number: 3001
---
apiVersion: v1
kind: Pod
metadata:
  name: failing
spec:
  containers:
  - name: nginx
    image: nginx:latest
    command: ["foo"]
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # has to match .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  minReadySeconds: 10 # by default is 0
  template:
    metadata:
      labels:
        app: nginx # has to match .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: registry.k8s.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

Screenshots

Short notifications

Screenshot 2022-10-10 at 16 43 49
Screenshot 2022-10-10 at 16 44 08

Long notifications

Screenshot 2022-10-10 at 16 48 19

Empty response

Screenshot 2022-10-11 at 14 03 09

Related issue(s)

#786

@pkosiec pkosiec added enhancement New feature or request slack labels Oct 10, 2022
@pkosiec pkosiec marked this pull request as ready for review October 11, 2022 12:03
@pkosiec pkosiec requested review from a team and PrasadG193 as code owners October 11, 2022 12:03
@pkosiec pkosiec added this to the v0.15.0 milestone Oct 11, 2022
Copy link
Contributor

@huseyinbabal huseyinbabal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request slack
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants