From 35db70f58c9b4abc4568c76390cc01dce2073921 Mon Sep 17 00:00:00 2001 From: Guilhem Lettron Date: Fri, 15 Nov 2024 16:56:09 +0100 Subject: [PATCH] feat: add a grpc plugin system --- cmd/switcher/switcher.go | 9 + pkg/store/kubeconfig_store_plugins.go | 153 ++++ pkg/store/plugins/buf.gen.yaml | 19 + pkg/store/plugins/buf.yaml | 10 + pkg/store/plugins/example/README.md | 15 + pkg/store/plugins/example/go.mod | 28 + pkg/store/plugins/example/go.sum | 68 ++ pkg/store/plugins/example/main.go | 83 +++ pkg/store/plugins/example/switch-config.yaml | 6 + pkg/store/plugins/grpc.go | 127 ++++ .../kubeconfigstore/v1/kubeconfig_store.pb.go | 660 ++++++++++++++++++ .../v1/kubeconfig_store_grpc.pb.go | 285 ++++++++ .../kubeconfigstore/v1/kubeconfig_store.proto | 61 ++ pkg/store/plugins/shared.go | 49 ++ pkg/store/types.go | 7 + types/config.go | 9 +- 16 files changed, 1588 insertions(+), 1 deletion(-) create mode 100644 pkg/store/kubeconfig_store_plugins.go create mode 100644 pkg/store/plugins/buf.gen.yaml create mode 100644 pkg/store/plugins/buf.yaml create mode 100644 pkg/store/plugins/example/README.md create mode 100644 pkg/store/plugins/example/go.mod create mode 100644 pkg/store/plugins/example/go.sum create mode 100644 pkg/store/plugins/example/main.go create mode 100644 pkg/store/plugins/example/switch-config.yaml create mode 100644 pkg/store/plugins/grpc.go create mode 100644 pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store.pb.go create mode 100644 pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store_grpc.pb.go create mode 100644 pkg/store/plugins/proto/kubeconfigstore/v1/kubeconfig_store.proto create mode 100644 pkg/store/plugins/shared.go diff --git a/cmd/switcher/switcher.go b/cmd/switcher/switcher.go index fff2e833..16482c49 100644 --- a/cmd/switcher/switcher.go +++ b/cmd/switcher/switcher.go @@ -316,6 +316,15 @@ func initialize() ([]storetypes.KubeconfigStore, *types.Config, error) { return nil, nil, err } s = capiStore + case types.StoreKindPlugin: + pluginStore, err := store.NewPluginStore(kubeconfigStoreFromConfig) + if err != nil { + if kubeconfigStoreFromConfig.Required != nil && !*kubeconfigStoreFromConfig.Required { + continue + } + return nil, nil, err + } + s = pluginStore default: return nil, nil, fmt.Errorf("unknown store %q", kubeconfigStoreFromConfig.Kind) } diff --git a/pkg/store/kubeconfig_store_plugins.go b/pkg/store/kubeconfig_store_plugins.go new file mode 100644 index 00000000..3bbba8cf --- /dev/null +++ b/pkg/store/kubeconfig_store_plugins.go @@ -0,0 +1,153 @@ +// Copyright 2024 The Kubeswitch authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package store + +import ( + "context" + "fmt" + "os/exec" + + "github.com/hashicorp/go-plugin" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + + "github.com/danielfoehrkn/kubeswitch/pkg/store/plugins" + storetypes "github.com/danielfoehrkn/kubeswitch/pkg/store/types" + "github.com/danielfoehrkn/kubeswitch/types" +) + +func NewPluginStore(store types.KubeconfigStore) (*PluginStore, error) { + storePlugin := &types.StoreConfigPlugin{} + if store.Config != nil { + buf, err := yaml.Marshal(store.Config) + if err != nil { + return nil, fmt.Errorf("failed to process plugin store config: %w", err) + } + + err = yaml.Unmarshal(buf, storePlugin) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal plugin config: %w", err) + } + } + + return &PluginStore{ + Logger: logrus.New().WithField("store", types.StoreKindPlugin), + KubeconfigStore: store, + Config: storePlugin, + }, nil +} + +// InitializePluginStore initializes the plugin store +func (s *PluginStore) InitializePluginStore() error { + + client := plugin.NewClient(&plugin.ClientConfig{ + HandshakeConfig: plugins.Handshake, + Plugins: plugins.PluginMap, + Cmd: exec.Command(s.Config.CmdPath, s.Config.Args...), + AllowedProtocols: []plugin.Protocol{ + plugin.ProtocolNetRPC, plugin.ProtocolGRPC}, + }) + + // Connect via RPC + rpcClient, err := client.Client() + if err != nil { + return err + } + + plugin, err := rpcClient.Dispense("store") + if err != nil { + return fmt.Errorf("failed to dispense plugin: %w", err) + } + + c, ok := plugin.(plugins.Store) + if !ok { + return fmt.Errorf("plugin does not implement Store interface") + } + + s.Client = c + + return nil +} + +// GetID returns the unique store ID +func (s *PluginStore) GetID() string { + ctx := context.Background() + + id, err := s.Client.GetID(ctx) + if err != nil { + return fmt.Sprintf("%s.default", s.GetKind()) + } + return id +} + +func (s *PluginStore) GetKind() types.StoreKind { + return types.StoreKindPlugin +} + +func (s *PluginStore) GetContextPrefix(path string) string { + ctx := context.Background() + + prefix, err := s.Client.GetContextPrefix(ctx, path) + if err != nil { + return fmt.Sprintf("%s/%s", s.GetKind(), path) + } + return prefix +} + +func (s *PluginStore) VerifyKubeconfigPaths() error { + ctx := context.Background() + + if err := s.InitializePluginStore(); err != nil { + return err + } + + return s.Client.VerifyKubeconfigPaths(ctx) +} + +func (s *PluginStore) GetStoreConfig() types.KubeconfigStore { + return s.KubeconfigStore +} + +func (s *PluginStore) GetLogger() *logrus.Entry { + return s.Logger +} + +func (s *PluginStore) StartSearch(channel chan storetypes.SearchResult) { + s.Logger.Debug("Plugin: start search") + + ctx := context.Background() + + if err := s.InitializePluginStore(); err != nil { + channel <- storetypes.SearchResult{ + KubeconfigPath: "", + Error: err, + } + return + } + + s.Client.StartSearch(ctx, channel) +} + +func (s *PluginStore) GetKubeconfigForPath(path string, tags map[string]string) ([]byte, error) { + s.Logger.Debugf("Plugins: get kubeconfig for path %s", path) + + ctx := context.Background() + + if err := s.InitializePluginStore(); err != nil { + return nil, err + } + + return s.Client.GetKubeconfigForPath(ctx, path, tags) +} diff --git a/pkg/store/plugins/buf.gen.yaml b/pkg/store/plugins/buf.gen.yaml new file mode 100644 index 00000000..0adb5f9c --- /dev/null +++ b/pkg/store/plugins/buf.gen.yaml @@ -0,0 +1,19 @@ +version: v2 +managed: + enabled: true + override: + - file_option: go_package_prefix + value: github.com/danielfoehrkn/kubeswitch/pkg/store/plugins +plugins: + - remote: buf.build/protocolbuffers/go:v1.35.1 + out: . + opt: + - paths=source_relative + - remote: buf.build/grpc/go:v1.5.1 + out: . + opt: + - paths=source_relative + - require_unimplemented_servers=false + +inputs: + - directory: proto diff --git a/pkg/store/plugins/buf.yaml b/pkg/store/plugins/buf.yaml new file mode 100644 index 00000000..53da97ac --- /dev/null +++ b/pkg/store/plugins/buf.yaml @@ -0,0 +1,10 @@ +# For details on buf.yaml configuration, visit https://buf.build/docs/configuration/v2/buf-yaml +version: v2 +modules: + - path: proto +lint: + use: + - STANDARD +breaking: + use: + - FILE diff --git a/pkg/store/plugins/example/README.md b/pkg/store/plugins/example/README.md new file mode 100644 index 00000000..5ce8cc83 --- /dev/null +++ b/pkg/store/plugins/example/README.md @@ -0,0 +1,15 @@ +# Plugin example + +This is an example plugin for the store. + +## Usage + +```yaml +kind: SwitchConfig +version: v1alpha1 +kubeconfigStores: +- kind: plugin + config: + cmdPath: /path/to/plugin + # args: +``` diff --git a/pkg/store/plugins/example/go.mod b/pkg/store/plugins/example/go.mod new file mode 100644 index 00000000..bcf4ca27 --- /dev/null +++ b/pkg/store/plugins/example/go.mod @@ -0,0 +1,28 @@ +module example.com/dumb-plugin + +go 1.23.3 + +require ( + github.com/danielfoehrkn/kubeswitch v0.0.0-00010101000000-000000000000 + github.com/hashicorp/go-hclog v1.6.3 + github.com/hashicorp/go-plugin v1.6.2 +) + +require ( + github.com/fatih/color v1.17.0 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/oklog/run v1.0.0 // indirect + github.com/sirupsen/logrus v1.9.3 // indirect + golang.org/x/net v0.30.0 // indirect + golang.org/x/sys v0.26.0 // indirect + golang.org/x/text v0.19.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect + google.golang.org/grpc v1.68.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + k8s.io/apimachinery v0.31.2 // indirect +) + +replace github.com/danielfoehrkn/kubeswitch => ../../../.. diff --git a/pkg/store/plugins/example/go.sum b/pkg/store/plugins/example/go.sum new file mode 100644 index 00000000..fad30000 --- /dev/null +++ b/pkg/store/plugins/example/go.sum @@ -0,0 +1,68 @@ +github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4= +github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k= +github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M= +github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog= +github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= +github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= +github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= +golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= +golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= +google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0= +google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/apimachinery v0.31.2 h1:i4vUt2hPK56W6mlT7Ry+AO8eEsyxMD1U44NR22CLTYw= +k8s.io/apimachinery v0.31.2/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= diff --git a/pkg/store/plugins/example/main.go b/pkg/store/plugins/example/main.go new file mode 100644 index 00000000..60203186 --- /dev/null +++ b/pkg/store/plugins/example/main.go @@ -0,0 +1,83 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package main + +import ( + "context" + + "github.com/hashicorp/go-hclog" + "github.com/hashicorp/go-plugin" + + "github.com/danielfoehrkn/kubeswitch/pkg/store/plugins" + storetypes "github.com/danielfoehrkn/kubeswitch/pkg/store/types" +) + +// Store is the implementation of the store plugin +type Store struct { + Logger hclog.Logger +} + +// GetID returns the ID of the store +func (s *Store) GetID(ctx context.Context) (string, error) { + return "example", nil +} + +// GetContextPrefix returns the context prefix +func (s *Store) GetContextPrefix(ctx context.Context, path string) (string, error) { + return "example", nil +} + +// VerifyKubeconfigPaths verifies the kubeconfig paths +func (s *Store) VerifyKubeconfigPaths(ctx context.Context) error { + return nil +} + +// StartSearch starts the search +func (s *Store) StartSearch(ctx context.Context, channel chan storetypes.SearchResult) { + channel <- storetypes.SearchResult{ + KubeconfigPath: "fake", + Error: nil, + } +} + +// GetKubeconfigForPath gets the kubeconfig for the path +func (s *Store) GetKubeconfigForPath(ctx context.Context, path string, tags map[string]string) ([]byte, error) { + if path == "fake" { + // valid fake kubeconfig + file := `apiVersion: v1 +kind: Config +preferences: {} + +clusters: +- name: development +- name: test + +users: +- name: developer +- name: experimenter + +contexts: +- name: dev-frontend +- name: dev-storage +- name: exp-test` + return []byte(file), nil + } + + s.Logger.Error("invalid path") + return nil, nil +} + +func main() { + logger := hclog.Default() + plugin.Serve(&plugin.ServeConfig{ + HandshakeConfig: plugins.Handshake, + Plugins: map[string]plugin.Plugin{ + "store": &plugins.StorePlugin{Impl: &Store{Logger: logger}}, + }, + Logger: logger, + + // A non-nil value here enables gRPC serving for this plugin... + GRPCServer: plugin.DefaultGRPCServer, + }) +} diff --git a/pkg/store/plugins/example/switch-config.yaml b/pkg/store/plugins/example/switch-config.yaml new file mode 100644 index 00000000..ee7e7fe4 --- /dev/null +++ b/pkg/store/plugins/example/switch-config.yaml @@ -0,0 +1,6 @@ +kind: SwitchConfig +version: v1alpha1 +kubeconfigStores: + - kind: plugin + config: + cmdPath: ./dumb-plugin diff --git a/pkg/store/plugins/grpc.go b/pkg/store/plugins/grpc.go new file mode 100644 index 00000000..35a866f8 --- /dev/null +++ b/pkg/store/plugins/grpc.go @@ -0,0 +1,127 @@ +package plugins + +import ( + "context" + "fmt" + + kubeconfigstorev1 "github.com/danielfoehrkn/kubeswitch/pkg/store/plugins/kubeconfigstore/v1" + storetypes "github.com/danielfoehrkn/kubeswitch/pkg/store/types" +) + +type GRPCClient struct { + Store + client kubeconfigstorev1.KubeconfigStoreServiceClient +} + +func (m *GRPCClient) GetID(ctx context.Context) (string, error) { + resp, err := m.client.GetID(ctx, &kubeconfigstorev1.GetIDRequest{}) + if err != nil { + return "", err + } + return resp.Id, nil +} + +func (m *GRPCClient) GetContextPrefix(ctx context.Context, path string) (string, error) { + resp, err := m.client.GetContextPrefix(ctx, &kubeconfigstorev1.GetContextPrefixRequest{Path: path}) + if err != nil { + return "", err + } + return resp.Prefix, nil +} + +func (m *GRPCClient) VerifyKubeconfigPaths(ctx context.Context) error { + _, err := m.client.VerifyKubeconfigPaths(ctx, &kubeconfigstorev1.VerifyKubeconfigPathsRequest{}) + return err +} + +func (m *GRPCClient) StartSearch(ctx context.Context, channel chan storetypes.SearchResult) { + stream, err := m.client.StartSearch(ctx, &kubeconfigstorev1.StartSearchRequest{}) + if err != nil { + channel <- storetypes.SearchResult{ + KubeconfigPath: "", + Error: err, + } + return + } + + for { + resp, err := stream.Recv() + if err != nil { + close(channel) + return + } + + channel <- storetypes.SearchResult{ + KubeconfigPath: resp.KubeconfigPath, + Tags: resp.Tags, + Error: err, + } + } +} + +func (m *GRPCClient) GetKubeconfigForPath(ctx context.Context, path string, tags map[string]string) ([]byte, error) { + resp, err := m.client.GetKubeconfigForPath(ctx, &kubeconfigstorev1.GetKubeconfigForPathRequest{Path: path}) + if err != nil { + return nil, err + } + + return resp.Kubeconfig, nil +} + +type GRPCServer struct { + // This is the real implementation + Impl Store +} + +func (m *GRPCServer) GetID( + ctx context.Context, + req *kubeconfigstorev1.GetIDRequest, +) (*kubeconfigstorev1.GetIDResponse, error) { + v, err := m.Impl.GetID(ctx) + return &kubeconfigstorev1.GetIDResponse{Id: v}, err +} + +func (m *GRPCServer) GetContextPrefix( + ctx context.Context, + req *kubeconfigstorev1.GetContextPrefixRequest, +) (*kubeconfigstorev1.GetContextPrefixResponse, error) { + v, err := m.Impl.GetContextPrefix(ctx, req.Path) + return &kubeconfigstorev1.GetContextPrefixResponse{Prefix: v}, err +} + +func (m *GRPCServer) VerifyKubeconfigPaths( + ctx context.Context, + req *kubeconfigstorev1.VerifyKubeconfigPathsRequest, +) (*kubeconfigstorev1.VerifyKubeconfigPathsResponse, error) { + err := m.Impl.VerifyKubeconfigPaths(ctx) + return &kubeconfigstorev1.VerifyKubeconfigPathsResponse{}, err +} + +func (m *GRPCServer) StartSearch( + req *kubeconfigstorev1.StartSearchRequest, + stream kubeconfigstorev1.KubeconfigStoreService_StartSearchServer, +) error { + ch := make(chan storetypes.SearchResult) + + if stream == nil { + return fmt.Errorf("stream is nil") + } + + ctx := stream.Context() + + go m.Impl.StartSearch(ctx, ch) + for v := range ch { + if err := stream.Send(&kubeconfigstorev1.StartSearchResponse{KubeconfigPath: v.KubeconfigPath, Tags: v.Tags}); err != nil { + return err + } + } + return nil +} + +func (m *GRPCServer) GetKubeconfigForPath( + ctx context.Context, + req *kubeconfigstorev1.GetKubeconfigForPathRequest, +) (*kubeconfigstorev1.GetKubeconfigForPathResponse, error) { + v, err := m.Impl.GetKubeconfigForPath(ctx, req.Path, req.Tags) + return &kubeconfigstorev1.GetKubeconfigForPathResponse{Kubeconfig: v}, err +} diff --git a/pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store.pb.go b/pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store.pb.go new file mode 100644 index 00000000..7d84df94 --- /dev/null +++ b/pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store.pb.go @@ -0,0 +1,660 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.35.1 +// protoc (unknown) +// source: kubeconfigstore/v1/kubeconfig_store.proto + +package kubeconfigstorev1 + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +// Request message for VerifyKubeconfigPaths RPC +type VerifyKubeconfigPathsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *VerifyKubeconfigPathsRequest) Reset() { + *x = VerifyKubeconfigPathsRequest{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VerifyKubeconfigPathsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VerifyKubeconfigPathsRequest) ProtoMessage() {} + +func (x *VerifyKubeconfigPathsRequest) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VerifyKubeconfigPathsRequest.ProtoReflect.Descriptor instead. +func (*VerifyKubeconfigPathsRequest) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{0} +} + +// Request message for StartSearch RPC +type StartSearchRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *StartSearchRequest) Reset() { + *x = StartSearchRequest{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartSearchRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartSearchRequest) ProtoMessage() {} + +func (x *StartSearchRequest) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartSearchRequest.ProtoReflect.Descriptor instead. +func (*StartSearchRequest) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{1} +} + +// Request message for GetID RPC +type GetIDRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetIDRequest) Reset() { + *x = GetIDRequest{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetIDRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetIDRequest) ProtoMessage() {} + +func (x *GetIDRequest) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetIDRequest.ProtoReflect.Descriptor instead. +func (*GetIDRequest) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{2} +} + +type GetIDResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *GetIDResponse) Reset() { + *x = GetIDResponse{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetIDResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetIDResponse) ProtoMessage() {} + +func (x *GetIDResponse) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetIDResponse.ProtoReflect.Descriptor instead. +func (*GetIDResponse) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{3} +} + +func (x *GetIDResponse) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type GetContextPrefixRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` +} + +func (x *GetContextPrefixRequest) Reset() { + *x = GetContextPrefixRequest{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetContextPrefixRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetContextPrefixRequest) ProtoMessage() {} + +func (x *GetContextPrefixRequest) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetContextPrefixRequest.ProtoReflect.Descriptor instead. +func (*GetContextPrefixRequest) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{4} +} + +func (x *GetContextPrefixRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +type GetContextPrefixResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Prefix string `protobuf:"bytes,1,opt,name=prefix,proto3" json:"prefix,omitempty"` +} + +func (x *GetContextPrefixResponse) Reset() { + *x = GetContextPrefixResponse{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetContextPrefixResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetContextPrefixResponse) ProtoMessage() {} + +func (x *GetContextPrefixResponse) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetContextPrefixResponse.ProtoReflect.Descriptor instead. +func (*GetContextPrefixResponse) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{5} +} + +func (x *GetContextPrefixResponse) GetPrefix() string { + if x != nil { + return x.Prefix + } + return "" +} + +type VerifyKubeconfigPathsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` // Example: "Verified" or "Error" +} + +func (x *VerifyKubeconfigPathsResponse) Reset() { + *x = VerifyKubeconfigPathsResponse{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *VerifyKubeconfigPathsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VerifyKubeconfigPathsResponse) ProtoMessage() {} + +func (x *VerifyKubeconfigPathsResponse) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VerifyKubeconfigPathsResponse.ProtoReflect.Descriptor instead. +func (*VerifyKubeconfigPathsResponse) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{6} +} + +func (x *VerifyKubeconfigPathsResponse) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +type StartSearchResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + KubeconfigPath string `protobuf:"bytes,1,opt,name=kubeconfig_path,json=kubeconfigPath,proto3" json:"kubeconfig_path,omitempty"` + Tags map[string]string `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + ErrorMessage string `protobuf:"bytes,3,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` +} + +func (x *StartSearchResponse) Reset() { + *x = StartSearchResponse{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *StartSearchResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StartSearchResponse) ProtoMessage() {} + +func (x *StartSearchResponse) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StartSearchResponse.ProtoReflect.Descriptor instead. +func (*StartSearchResponse) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{7} +} + +func (x *StartSearchResponse) GetKubeconfigPath() string { + if x != nil { + return x.KubeconfigPath + } + return "" +} + +func (x *StartSearchResponse) GetTags() map[string]string { + if x != nil { + return x.Tags + } + return nil +} + +func (x *StartSearchResponse) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +type GetKubeconfigForPathRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Path string `protobuf:"bytes,1,opt,name=path,proto3" json:"path,omitempty"` + Tags map[string]string `protobuf:"bytes,2,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *GetKubeconfigForPathRequest) Reset() { + *x = GetKubeconfigForPathRequest{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetKubeconfigForPathRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetKubeconfigForPathRequest) ProtoMessage() {} + +func (x *GetKubeconfigForPathRequest) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetKubeconfigForPathRequest.ProtoReflect.Descriptor instead. +func (*GetKubeconfigForPathRequest) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{8} +} + +func (x *GetKubeconfigForPathRequest) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + +func (x *GetKubeconfigForPathRequest) GetTags() map[string]string { + if x != nil { + return x.Tags + } + return nil +} + +type GetKubeconfigForPathResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Kubeconfig []byte `protobuf:"bytes,1,opt,name=kubeconfig,proto3" json:"kubeconfig,omitempty"` + ErrorMessage string `protobuf:"bytes,2,opt,name=error_message,json=errorMessage,proto3" json:"error_message,omitempty"` +} + +func (x *GetKubeconfigForPathResponse) Reset() { + *x = GetKubeconfigForPathResponse{} + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetKubeconfigForPathResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetKubeconfigForPathResponse) ProtoMessage() {} + +func (x *GetKubeconfigForPathResponse) ProtoReflect() protoreflect.Message { + mi := &file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetKubeconfigForPathResponse.ProtoReflect.Descriptor instead. +func (*GetKubeconfigForPathResponse) Descriptor() ([]byte, []int) { + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP(), []int{9} +} + +func (x *GetKubeconfigForPathResponse) GetKubeconfig() []byte { + if x != nil { + return x.Kubeconfig + } + return nil +} + +func (x *GetKubeconfigForPathResponse) GetErrorMessage() string { + if x != nil { + return x.ErrorMessage + } + return "" +} + +var File_kubeconfigstore_v1_kubeconfig_store_proto protoreflect.FileDescriptor + +var file_kubeconfigstore_v1_kubeconfig_store_proto_rawDesc = []byte{ + 0x0a, 0x29, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x6b, 0x75, 0x62, + 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x22, + 0x1e, 0x0a, 0x1c, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, + 0x14, 0x0a, 0x12, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x49, 0x44, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1f, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x49, 0x44, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x22, 0x2d, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x70, 0x61, 0x74, 0x68, 0x22, 0x32, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x22, 0x37, 0x0a, 0x1d, 0x56, 0x65, 0x72, + 0x69, 0x66, 0x79, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, + 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0xe3, 0x01, 0x0a, 0x13, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x6b, 0x75, + 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x45, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x31, 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, + 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, + 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, + 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, + 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xb9, 0x01, 0x0a, 0x1b, 0x47, 0x65, 0x74, + 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, + 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x4d, 0x0a, 0x04, + 0x74, 0x61, 0x67, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x6b, 0x75, 0x62, + 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6f, 0x72, + 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x54, 0x61, 0x67, 0x73, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x54, + 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0x63, 0x0a, 0x1c, 0x47, 0x65, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x5f, 0x6d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x32, 0xb0, 0x04, 0x0a, 0x16, 0x4b, 0x75, + 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x4c, 0x0a, 0x05, 0x47, 0x65, 0x74, 0x49, 0x44, 0x12, 0x20, 0x2e, + 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x44, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x21, 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x6d, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x2b, 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x78, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x7c, 0x0a, 0x15, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4b, 0x75, 0x62, 0x65, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x30, 0x2e, 0x6b, 0x75, 0x62, + 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x6b, + 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, + 0x31, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x60, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x26, + 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x30, + 0x01, 0x12, 0x79, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x46, 0x6f, 0x72, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2f, 0x2e, 0x6b, 0x75, 0x62, 0x65, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6f, 0x72, 0x50, + 0x61, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x6b, 0x75, 0x62, + 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x46, 0x6f, 0x72, + 0x50, 0x61, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0xf3, 0x01, 0x0a, + 0x16, 0x63, 0x6f, 0x6d, 0x2e, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, + 0x74, 0x6f, 0x72, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, + 0x5a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x64, 0x61, 0x6e, 0x69, + 0x65, 0x6c, 0x66, 0x6f, 0x65, 0x68, 0x72, 0x6b, 0x6e, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x73, 0x77, + 0x69, 0x74, 0x63, 0x68, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x70, + 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x73, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x6b, 0x75, 0x62, 0x65, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x4b, 0x58, + 0x58, 0xaa, 0x02, 0x12, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, + 0x6f, 0x72, 0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x4b, 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x1e, 0x4b, 0x75, + 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5c, 0x56, 0x31, + 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x13, 0x4b, + 0x75, 0x62, 0x65, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3a, 0x3a, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescOnce sync.Once + file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescData = file_kubeconfigstore_v1_kubeconfig_store_proto_rawDesc +) + +func file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescGZIP() []byte { + file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescOnce.Do(func() { + file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescData = protoimpl.X.CompressGZIP(file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescData) + }) + return file_kubeconfigstore_v1_kubeconfig_store_proto_rawDescData +} + +var file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_kubeconfigstore_v1_kubeconfig_store_proto_goTypes = []any{ + (*VerifyKubeconfigPathsRequest)(nil), // 0: kubeconfigstore.v1.VerifyKubeconfigPathsRequest + (*StartSearchRequest)(nil), // 1: kubeconfigstore.v1.StartSearchRequest + (*GetIDRequest)(nil), // 2: kubeconfigstore.v1.GetIDRequest + (*GetIDResponse)(nil), // 3: kubeconfigstore.v1.GetIDResponse + (*GetContextPrefixRequest)(nil), // 4: kubeconfigstore.v1.GetContextPrefixRequest + (*GetContextPrefixResponse)(nil), // 5: kubeconfigstore.v1.GetContextPrefixResponse + (*VerifyKubeconfigPathsResponse)(nil), // 6: kubeconfigstore.v1.VerifyKubeconfigPathsResponse + (*StartSearchResponse)(nil), // 7: kubeconfigstore.v1.StartSearchResponse + (*GetKubeconfigForPathRequest)(nil), // 8: kubeconfigstore.v1.GetKubeconfigForPathRequest + (*GetKubeconfigForPathResponse)(nil), // 9: kubeconfigstore.v1.GetKubeconfigForPathResponse + nil, // 10: kubeconfigstore.v1.StartSearchResponse.TagsEntry + nil, // 11: kubeconfigstore.v1.GetKubeconfigForPathRequest.TagsEntry +} +var file_kubeconfigstore_v1_kubeconfig_store_proto_depIdxs = []int32{ + 10, // 0: kubeconfigstore.v1.StartSearchResponse.tags:type_name -> kubeconfigstore.v1.StartSearchResponse.TagsEntry + 11, // 1: kubeconfigstore.v1.GetKubeconfigForPathRequest.tags:type_name -> kubeconfigstore.v1.GetKubeconfigForPathRequest.TagsEntry + 2, // 2: kubeconfigstore.v1.KubeconfigStoreService.GetID:input_type -> kubeconfigstore.v1.GetIDRequest + 4, // 3: kubeconfigstore.v1.KubeconfigStoreService.GetContextPrefix:input_type -> kubeconfigstore.v1.GetContextPrefixRequest + 0, // 4: kubeconfigstore.v1.KubeconfigStoreService.VerifyKubeconfigPaths:input_type -> kubeconfigstore.v1.VerifyKubeconfigPathsRequest + 1, // 5: kubeconfigstore.v1.KubeconfigStoreService.StartSearch:input_type -> kubeconfigstore.v1.StartSearchRequest + 8, // 6: kubeconfigstore.v1.KubeconfigStoreService.GetKubeconfigForPath:input_type -> kubeconfigstore.v1.GetKubeconfigForPathRequest + 3, // 7: kubeconfigstore.v1.KubeconfigStoreService.GetID:output_type -> kubeconfigstore.v1.GetIDResponse + 5, // 8: kubeconfigstore.v1.KubeconfigStoreService.GetContextPrefix:output_type -> kubeconfigstore.v1.GetContextPrefixResponse + 6, // 9: kubeconfigstore.v1.KubeconfigStoreService.VerifyKubeconfigPaths:output_type -> kubeconfigstore.v1.VerifyKubeconfigPathsResponse + 7, // 10: kubeconfigstore.v1.KubeconfigStoreService.StartSearch:output_type -> kubeconfigstore.v1.StartSearchResponse + 9, // 11: kubeconfigstore.v1.KubeconfigStoreService.GetKubeconfigForPath:output_type -> kubeconfigstore.v1.GetKubeconfigForPathResponse + 7, // [7:12] is the sub-list for method output_type + 2, // [2:7] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name +} + +func init() { file_kubeconfigstore_v1_kubeconfig_store_proto_init() } +func file_kubeconfigstore_v1_kubeconfig_store_proto_init() { + if File_kubeconfigstore_v1_kubeconfig_store_proto != nil { + return + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_kubeconfigstore_v1_kubeconfig_store_proto_rawDesc, + NumEnums: 0, + NumMessages: 12, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_kubeconfigstore_v1_kubeconfig_store_proto_goTypes, + DependencyIndexes: file_kubeconfigstore_v1_kubeconfig_store_proto_depIdxs, + MessageInfos: file_kubeconfigstore_v1_kubeconfig_store_proto_msgTypes, + }.Build() + File_kubeconfigstore_v1_kubeconfig_store_proto = out.File + file_kubeconfigstore_v1_kubeconfig_store_proto_rawDesc = nil + file_kubeconfigstore_v1_kubeconfig_store_proto_goTypes = nil + file_kubeconfigstore_v1_kubeconfig_store_proto_depIdxs = nil +} diff --git a/pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store_grpc.pb.go b/pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store_grpc.pb.go new file mode 100644 index 00000000..dc1a4c0c --- /dev/null +++ b/pkg/store/plugins/kubeconfigstore/v1/kubeconfig_store_grpc.pb.go @@ -0,0 +1,285 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc (unknown) +// source: kubeconfigstore/v1/kubeconfig_store.proto + +package kubeconfigstorev1 + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + KubeconfigStoreService_GetID_FullMethodName = "/kubeconfigstore.v1.KubeconfigStoreService/GetID" + KubeconfigStoreService_GetContextPrefix_FullMethodName = "/kubeconfigstore.v1.KubeconfigStoreService/GetContextPrefix" + KubeconfigStoreService_VerifyKubeconfigPaths_FullMethodName = "/kubeconfigstore.v1.KubeconfigStoreService/VerifyKubeconfigPaths" + KubeconfigStoreService_StartSearch_FullMethodName = "/kubeconfigstore.v1.KubeconfigStoreService/StartSearch" + KubeconfigStoreService_GetKubeconfigForPath_FullMethodName = "/kubeconfigstore.v1.KubeconfigStoreService/GetKubeconfigForPath" +) + +// KubeconfigStoreServiceClient is the client API for KubeconfigStoreService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type KubeconfigStoreServiceClient interface { + // Retrieves the unique store ID + GetID(ctx context.Context, in *GetIDRequest, opts ...grpc.CallOption) (*GetIDResponse, error) + // Retrieves the prefix for the kubeconfig context names + GetContextPrefix(ctx context.Context, in *GetContextPrefixRequest, opts ...grpc.CallOption) (*GetContextPrefixResponse, error) + // Verifies the kubeconfig search paths + VerifyKubeconfigPaths(ctx context.Context, in *VerifyKubeconfigPathsRequest, opts ...grpc.CallOption) (*VerifyKubeconfigPathsResponse, error) + // Starts the search and streams results + StartSearch(ctx context.Context, in *StartSearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StartSearchResponse], error) + // Retrieves kubeconfig bytes for a given path and optional tags + GetKubeconfigForPath(ctx context.Context, in *GetKubeconfigForPathRequest, opts ...grpc.CallOption) (*GetKubeconfigForPathResponse, error) +} + +type kubeconfigStoreServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewKubeconfigStoreServiceClient(cc grpc.ClientConnInterface) KubeconfigStoreServiceClient { + return &kubeconfigStoreServiceClient{cc} +} + +func (c *kubeconfigStoreServiceClient) GetID(ctx context.Context, in *GetIDRequest, opts ...grpc.CallOption) (*GetIDResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetIDResponse) + err := c.cc.Invoke(ctx, KubeconfigStoreService_GetID_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *kubeconfigStoreServiceClient) GetContextPrefix(ctx context.Context, in *GetContextPrefixRequest, opts ...grpc.CallOption) (*GetContextPrefixResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetContextPrefixResponse) + err := c.cc.Invoke(ctx, KubeconfigStoreService_GetContextPrefix_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *kubeconfigStoreServiceClient) VerifyKubeconfigPaths(ctx context.Context, in *VerifyKubeconfigPathsRequest, opts ...grpc.CallOption) (*VerifyKubeconfigPathsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(VerifyKubeconfigPathsResponse) + err := c.cc.Invoke(ctx, KubeconfigStoreService_VerifyKubeconfigPaths_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *kubeconfigStoreServiceClient) StartSearch(ctx context.Context, in *StartSearchRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[StartSearchResponse], error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + stream, err := c.cc.NewStream(ctx, &KubeconfigStoreService_ServiceDesc.Streams[0], KubeconfigStoreService_StartSearch_FullMethodName, cOpts...) + if err != nil { + return nil, err + } + x := &grpc.GenericClientStream[StartSearchRequest, StartSearchResponse]{ClientStream: stream} + if err := x.ClientStream.SendMsg(in); err != nil { + return nil, err + } + if err := x.ClientStream.CloseSend(); err != nil { + return nil, err + } + return x, nil +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type KubeconfigStoreService_StartSearchClient = grpc.ServerStreamingClient[StartSearchResponse] + +func (c *kubeconfigStoreServiceClient) GetKubeconfigForPath(ctx context.Context, in *GetKubeconfigForPathRequest, opts ...grpc.CallOption) (*GetKubeconfigForPathResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetKubeconfigForPathResponse) + err := c.cc.Invoke(ctx, KubeconfigStoreService_GetKubeconfigForPath_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// KubeconfigStoreServiceServer is the server API for KubeconfigStoreService service. +// All implementations should embed UnimplementedKubeconfigStoreServiceServer +// for forward compatibility. +type KubeconfigStoreServiceServer interface { + // Retrieves the unique store ID + GetID(context.Context, *GetIDRequest) (*GetIDResponse, error) + // Retrieves the prefix for the kubeconfig context names + GetContextPrefix(context.Context, *GetContextPrefixRequest) (*GetContextPrefixResponse, error) + // Verifies the kubeconfig search paths + VerifyKubeconfigPaths(context.Context, *VerifyKubeconfigPathsRequest) (*VerifyKubeconfigPathsResponse, error) + // Starts the search and streams results + StartSearch(*StartSearchRequest, grpc.ServerStreamingServer[StartSearchResponse]) error + // Retrieves kubeconfig bytes for a given path and optional tags + GetKubeconfigForPath(context.Context, *GetKubeconfigForPathRequest) (*GetKubeconfigForPathResponse, error) +} + +// UnimplementedKubeconfigStoreServiceServer should be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedKubeconfigStoreServiceServer struct{} + +func (UnimplementedKubeconfigStoreServiceServer) GetID(context.Context, *GetIDRequest) (*GetIDResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetID not implemented") +} +func (UnimplementedKubeconfigStoreServiceServer) GetContextPrefix(context.Context, *GetContextPrefixRequest) (*GetContextPrefixResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetContextPrefix not implemented") +} +func (UnimplementedKubeconfigStoreServiceServer) VerifyKubeconfigPaths(context.Context, *VerifyKubeconfigPathsRequest) (*VerifyKubeconfigPathsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method VerifyKubeconfigPaths not implemented") +} +func (UnimplementedKubeconfigStoreServiceServer) StartSearch(*StartSearchRequest, grpc.ServerStreamingServer[StartSearchResponse]) error { + return status.Errorf(codes.Unimplemented, "method StartSearch not implemented") +} +func (UnimplementedKubeconfigStoreServiceServer) GetKubeconfigForPath(context.Context, *GetKubeconfigForPathRequest) (*GetKubeconfigForPathResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetKubeconfigForPath not implemented") +} +func (UnimplementedKubeconfigStoreServiceServer) testEmbeddedByValue() {} + +// UnsafeKubeconfigStoreServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to KubeconfigStoreServiceServer will +// result in compilation errors. +type UnsafeKubeconfigStoreServiceServer interface { + mustEmbedUnimplementedKubeconfigStoreServiceServer() +} + +func RegisterKubeconfigStoreServiceServer(s grpc.ServiceRegistrar, srv KubeconfigStoreServiceServer) { + // If the following call pancis, it indicates UnimplementedKubeconfigStoreServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&KubeconfigStoreService_ServiceDesc, srv) +} + +func _KubeconfigStoreService_GetID_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetIDRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KubeconfigStoreServiceServer).GetID(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: KubeconfigStoreService_GetID_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KubeconfigStoreServiceServer).GetID(ctx, req.(*GetIDRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KubeconfigStoreService_GetContextPrefix_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetContextPrefixRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KubeconfigStoreServiceServer).GetContextPrefix(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: KubeconfigStoreService_GetContextPrefix_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KubeconfigStoreServiceServer).GetContextPrefix(ctx, req.(*GetContextPrefixRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KubeconfigStoreService_VerifyKubeconfigPaths_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(VerifyKubeconfigPathsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KubeconfigStoreServiceServer).VerifyKubeconfigPaths(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: KubeconfigStoreService_VerifyKubeconfigPaths_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KubeconfigStoreServiceServer).VerifyKubeconfigPaths(ctx, req.(*VerifyKubeconfigPathsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _KubeconfigStoreService_StartSearch_Handler(srv interface{}, stream grpc.ServerStream) error { + m := new(StartSearchRequest) + if err := stream.RecvMsg(m); err != nil { + return err + } + return srv.(KubeconfigStoreServiceServer).StartSearch(m, &grpc.GenericServerStream[StartSearchRequest, StartSearchResponse]{ServerStream: stream}) +} + +// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. +type KubeconfigStoreService_StartSearchServer = grpc.ServerStreamingServer[StartSearchResponse] + +func _KubeconfigStoreService_GetKubeconfigForPath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetKubeconfigForPathRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(KubeconfigStoreServiceServer).GetKubeconfigForPath(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: KubeconfigStoreService_GetKubeconfigForPath_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(KubeconfigStoreServiceServer).GetKubeconfigForPath(ctx, req.(*GetKubeconfigForPathRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// KubeconfigStoreService_ServiceDesc is the grpc.ServiceDesc for KubeconfigStoreService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var KubeconfigStoreService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "kubeconfigstore.v1.KubeconfigStoreService", + HandlerType: (*KubeconfigStoreServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetID", + Handler: _KubeconfigStoreService_GetID_Handler, + }, + { + MethodName: "GetContextPrefix", + Handler: _KubeconfigStoreService_GetContextPrefix_Handler, + }, + { + MethodName: "VerifyKubeconfigPaths", + Handler: _KubeconfigStoreService_VerifyKubeconfigPaths_Handler, + }, + { + MethodName: "GetKubeconfigForPath", + Handler: _KubeconfigStoreService_GetKubeconfigForPath_Handler, + }, + }, + Streams: []grpc.StreamDesc{ + { + StreamName: "StartSearch", + Handler: _KubeconfigStoreService_StartSearch_Handler, + ServerStreams: true, + }, + }, + Metadata: "kubeconfigstore/v1/kubeconfig_store.proto", +} diff --git a/pkg/store/plugins/proto/kubeconfigstore/v1/kubeconfig_store.proto b/pkg/store/plugins/proto/kubeconfigstore/v1/kubeconfig_store.proto new file mode 100644 index 00000000..cd224a5f --- /dev/null +++ b/pkg/store/plugins/proto/kubeconfigstore/v1/kubeconfig_store.proto @@ -0,0 +1,61 @@ +syntax = "proto3"; + +package kubeconfigstore.v1; + +service KubeconfigStoreService { + // Retrieves the unique store ID + rpc GetID(GetIDRequest) returns (GetIDResponse); + + // Retrieves the prefix for the kubeconfig context names + rpc GetContextPrefix(GetContextPrefixRequest) returns (GetContextPrefixResponse); + + // Verifies the kubeconfig search paths + rpc VerifyKubeconfigPaths(VerifyKubeconfigPathsRequest) returns (VerifyKubeconfigPathsResponse); + + // Starts the search and streams results + rpc StartSearch(StartSearchRequest) returns (stream StartSearchResponse); + + // Retrieves kubeconfig bytes for a given path and optional tags + rpc GetKubeconfigForPath(GetKubeconfigForPathRequest) returns (GetKubeconfigForPathResponse); +} + +// Request message for VerifyKubeconfigPaths RPC +message VerifyKubeconfigPathsRequest {} + +// Request message for StartSearch RPC +message StartSearchRequest {} + +// Request message for GetID RPC +message GetIDRequest {} + +message GetIDResponse { + string id = 1; +} + +message GetContextPrefixRequest { + string path = 1; +} + +message GetContextPrefixResponse { + string prefix = 1; +} + +message VerifyKubeconfigPathsResponse { + string status = 1; // Example: "Verified" or "Error" +} + +message StartSearchResponse { + string kubeconfig_path = 1; + map tags = 2; + string error_message = 3; +} + +message GetKubeconfigForPathRequest { + string path = 1; + map tags = 2; +} + +message GetKubeconfigForPathResponse { + bytes kubeconfig = 1; + string error_message = 2; +} diff --git a/pkg/store/plugins/shared.go b/pkg/store/plugins/shared.go new file mode 100644 index 00000000..890212c8 --- /dev/null +++ b/pkg/store/plugins/shared.go @@ -0,0 +1,49 @@ +package plugins + +import ( + "context" + + "github.com/hashicorp/go-plugin" + "google.golang.org/grpc" + + kubeconfigstorev1 "github.com/danielfoehrkn/kubeswitch/pkg/store/plugins/kubeconfigstore/v1" + storetypes "github.com/danielfoehrkn/kubeswitch/pkg/store/types" +) + +var Handshake = plugin.HandshakeConfig{ + ProtocolVersion: 1, + MagicCookieKey: "BASIC_PLUGIN", + MagicCookieValue: "hello", +} + +type Store interface { + GetID(ctx context.Context) (string, error) + GetContextPrefix(ctx context.Context, path string) (string, error) + VerifyKubeconfigPaths(ctx context.Context) error + StartSearch(ctx context.Context, channel chan storetypes.SearchResult) + GetKubeconfigForPath(ctx context.Context, path string, tags map[string]string) ([]byte, error) +} + +// PluginMap is the map of plugins we can dispense. +var PluginMap = map[string]plugin.Plugin{ + "store": &StorePlugin{}, +} + +// StorePlugin is the implementation of plugin.Plugin so we can serve/consume this. +type StorePlugin struct { + plugin.NetRPCUnsupportedPlugin + + Impl Store +} + +func (p *StorePlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error { + kubeconfigstorev1.RegisterKubeconfigStoreServiceServer(s, &GRPCServer{Impl: p.Impl}) + + return nil +} + +func (p *StorePlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) { + return &GRPCClient{client: kubeconfigstorev1.NewKubeconfigStoreServiceClient(c)}, nil +} + +var _ plugin.GRPCPlugin = &StorePlugin{} diff --git a/pkg/store/types.go b/pkg/store/types.go index 6fa41475..4b381d89 100644 --- a/pkg/store/types.go +++ b/pkg/store/types.go @@ -164,3 +164,10 @@ type CapiStore struct { Client client.Client Config *types.StoreConfigCapi } + +type PluginStore struct { + Logger *logrus.Entry + KubeconfigStore types.KubeconfigStore + Config *types.StoreConfigPlugin + Client plugins.Store +} diff --git a/types/config.go b/types/config.go index 7485c29c..5c6f5793 100644 --- a/types/config.go +++ b/types/config.go @@ -24,7 +24,7 @@ import ( type StoreKind string // ValidStoreKinds contains all valid store kinds -var ValidStoreKinds = sets.NewString(string(StoreKindVault), string(StoreKindFilesystem), string(StoreKindGardener), string(StoreKindGKE), string(StoreKindAzure), string(StoreKindEKS), string(StoreKindRancher), string(StoreKindOVH), string(StoreKindScaleway), string(StoreKindDigitalOcean), string(StoreKindAkamai), string(StoreKindCapi)) +var ValidStoreKinds = sets.NewString(string(StoreKindVault), string(StoreKindFilesystem), string(StoreKindGardener), string(StoreKindGKE), string(StoreKindAzure), string(StoreKindEKS), string(StoreKindRancher), string(StoreKindOVH), string(StoreKindScaleway), string(StoreKindDigitalOcean), string(StoreKindAkamai), string(StoreKindCapi), string(StoreKindPlugin)) // ValidConfigVersions contains all valid config versions var ValidConfigVersions = sets.NewString("v1alpha1") @@ -54,6 +54,8 @@ const ( StoreKindAkamai StoreKind = "akamai" // StoreKindCapi is an identifier for the CAPI store StoreKindCapi StoreKind = "capi" + // StoreKindPlugin is an identifier for the Plugin store + StoreKindPlugin StoreKind = "plugin" ) type Config struct { @@ -264,3 +266,8 @@ type StoreConfigCapi struct { // for the management cluster KubeconfigPath string `yaml:"kubeconfigPath"` } + +type StoreConfigPlugin struct { + CmdPath string `yaml:"cmdPath"` + Args []string `yaml:"args"` +}