1"use strict";(self.webpackChunkdocusaurus_website=self.webpackChunkdocusaurus_website||[]).push([[3357],{92585:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>u,default:()=>g,frontMatter:()=>r,metadata:()=>s,toc:()=>l});var o=t(85893),i=t(11151);const r={id:"using-kubeconfig",title:"Using kubeconfig",sidebar_position:4},u=void 0,s={id:"plugins/development/using-kubeconfig",title:"Using kubeconfig",description:"You can request Botkube to generate and pass kubeconfig file to your plugin by adding RBAC section",source:"@site/docs/plugins/development/using-kubeconfig.md",sourceDirName:"plugins/development",slug:"/plugins/development/using-kubeconfig",permalink:"/next/plugins/development/using-kubeconfig",draft:!1,unlisted:!1,editUrl:"https://github.com/kubeshop/botkube-docs/edit/main/docs/plugins/development/using-kubeconfig.md",tags:[],version:"current",sidebarPosition:4,frontMatter:{id:"using-kubeconfig",title:"Using kubeconfig",sidebar_position:4},sidebar:"docsSidebar",previous:{title:"Custom source",permalink:"/next/plugins/development/custom-source"},next:{title:"Interactive messages",permalink:"/next/plugins/development/interactive-messages"}},c={},l=[];function a(e){const n={a:"a",code:"code",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",...(0,i.a)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsxs)(n.p,{children:["You can request Botkube to generate and pass kubeconfig file to your plugin by adding RBAC section\nto your plugin configuration. The following example requests a kubeconfig that impersonates\nuser ",(0,o.jsx)(n.strong,{children:"User.rbac.authorization.k8s.io"})," ",(0,o.jsx)(n.code,{children:"read-only-user"}),". For more information refer to the\n",(0,o.jsx)(n.a,{href:"/next/features/rbac",children:"RBAC section"}),". The example is for executor plugins, source plugins\ncan access kubeconfig in their ",(0,o.jsx)(n.code,{children:"Stream()"})," function in ",(0,o.jsx)(n.code,{children:"source.StreamInput"}),"."]}),"\n",(0,o.jsx)(n.p,{children:"RBAC config for an example plugin:"}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-yaml",children:'executors:\n "reader-team-a":\n kube-reader:\n enabled: true\n context:\n user:\n type: Static\n static:\n value: read-only-user\n'})}),"\n",(0,o.jsxs)(n.p,{children:["The kubeconfig is available in ",(0,o.jsx)(n.code,{children:"executor.ExecuteInput"})," as a slice of bytes.\nThere are two options to instantiate a Kubernetes Go client with this config."]}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsx)(n.li,{children:"From bytes"}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'import (\n\t"context"\n\t"k8s.io/client-go/tools/clientcmd"\n\t"k8s.io/client-go/kubernetes"\n\t"github.com/kubeshop/botkube/pkg/api/executor"\n\t"github.com/kubeshop/botkube/pkg/pluginx"\n)\n\nfunc (ReaderExecutor) Execute(_ context.Context, in executor.ExecuteInput) (executor.ExecuteOutput, error) {\n\tconfig, err := clientcmd.RESTConfigFromKubeConfig(in.Context.KubeConfig)\n\tif err != nil {\n\t\treturn executor.ExecuteOutput{}, err\n\t}\n\tclientset, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\treturn executor.ExecuteOutput{}, err\n\t}\n\t...\n}\n'})}),"\n",(0,o.jsxs)(n.ol,{start:"2",children:["\n",(0,o.jsx)(n.li,{children:"From file"}),"\n"]}),"\n",(0,o.jsx)(n.pre,{children:(0,o.jsx)(n.code,{className:"language-go",children:'import (\n\t"context"\n\t"k8s.io/client-go/tools/clientcmd"\n\t"k8s.io/client-go/kubernetes"\n\t"github.com/kubeshop/botkube/pkg/api/executor"\n\t"github.com/kubeshop/botkube/pkg/pluginx"\n)\n\nfunc (ReaderExecutor) Execute(ctx context.Context, in executor.ExecuteInput) (executor.ExecuteOutput, error) {\n\tkubeConfigPath, deleteFn, err := pluginx.PersistKubeConfig(ctx, in.Context.KubeConfig)\n\tif err != nil {\n\t\treturn executor.ExecuteOutput{}, fmt.Errorf("while writing kubeconfig file: %w", err)\n\t}\n\tdefer func() {\n\t\tif deleteErr := deleteFn(ctx); deleteErr != nil {\n\t\t\tfmt.Fprintf(os.Stderr, "failed to delete kubeconfig file %s: %v", kubeConfigPath, deleteErr)\n\t\t}\n\t}()\n\tconfig, err := clientcmd.BuildConfigFromFlags("", kubeConfigPath)\n\tif err != nil {\n\t\treturn executor.ExecuteOutput{}, err\n\t}\n\tclientset, err := kubernetes.NewForConfig(config)\n\tif err != nil {\n\t\treturn executor.ExecuteOutput{}, err\n\t}\n ...\n}\n'})})]})}function g(e={}){const{wrapper:n}={...(0,i.a)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(a,{...e})}):a(e)}},11151:(e,n,t)=>{t.d(n,{Z:()=>s,a:()=>u});var o=t(67294);const i={},r=o.createContext(i);function u(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:u(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.