feat: Enhance PipeSpec and FromSpec with AuthorizedKeysSecret (#581)
* feat: Enhance PipeSpec and FromSpec with AuthorizedKeysSecret - Added AuthorizedKeysSecret field to FromSpec for referencing Kubernetes secrets. - Updated deepcopy functions to handle new AuthorizedKeysSecret field. - Modified CRD definition to include the new private_key_secret field. - Refactored fake client and lister implementations to support new fields. - Introduced shared informers and listers for Pipe resources. - Updated code generation scripts to reflect changes in API structure. * refactor: Rename private_key_secret to authorized_keys_secret in CRD schema * feat: Add support for authorized_keys from secret in skel and update k8sworkload.yaml * feat: Enhance authorized keys handling to include secret name check * Update plugin/kubernetes/skel.go Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
ca311e15cd
commit
706a36b40e
19 changed files with 573 additions and 301 deletions
|
|
@ -20,12 +20,13 @@ type PipeSpec struct {
|
|||
}
|
||||
|
||||
type FromSpec struct {
|
||||
Username string `json:"username"`
|
||||
UsernameRegexMatch bool `json:"username_regex_match,omitempty"`
|
||||
AuthorizedKeysData string `json:"authorized_keys_data,omitempty"`
|
||||
HtpasswdData string `json:"htpasswd_data,omitempty"`
|
||||
AuthorizedKeysFile string `json:"authorized_keys_file,omitempty"`
|
||||
HtpasswdFile string `json:"htpasswd_file,omitempty"`
|
||||
Username string `json:"username"`
|
||||
UsernameRegexMatch bool `json:"username_regex_match,omitempty"`
|
||||
AuthorizedKeysData string `json:"authorized_keys_data,omitempty"`
|
||||
AuthorizedKeysFile string `json:"authorized_keys_file,omitempty"`
|
||||
AuthorizedKeysSecret corev1.LocalObjectReference `json:"authorized_keys_secret,omitempty"`
|
||||
HtpasswdData string `json:"htpasswd_data,omitempty"`
|
||||
HtpasswdFile string `json:"htpasswd_file,omitempty"`
|
||||
}
|
||||
|
||||
type ToSpec struct {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FromSpec) DeepCopyInto(out *FromSpec) {
|
||||
*out = *in
|
||||
out.AuthorizedKeysSecret = in.AuthorizedKeysSecret
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -111,6 +112,7 @@ func (in *PipeSpec) DeepCopy() *PipeSpec {
|
|||
func (in *ToSpec) DeepCopyInto(out *ToSpec) {
|
||||
*out = *in
|
||||
out.PrivateKeySecret = in.PrivateKeySecret
|
||||
out.PasswordSecret = in.PasswordSecret
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,6 +36,15 @@ spec:
|
|||
type: string
|
||||
authorized_keys_file:
|
||||
type: string
|
||||
authorized_keys_secret:
|
||||
description: LocalObjectReference contains enough information
|
||||
to let you locate the referenced object inside the same namespace.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
username:
|
||||
type: string
|
||||
htpasswd_data:
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
package versioned
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
fmt "fmt"
|
||||
http "net/http"
|
||||
|
||||
sshpiperv1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned/typed/sshpiper/v1beta1"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
|
|
|
|||
|
|
@ -15,8 +15,12 @@ import (
|
|||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
//
|
||||
// DEPRECATED: NewClientset replaces this with support for field management, which significantly improves
|
||||
// server side apply testing. NewClientset is only available when apply configurations are generated (e.g.
|
||||
// via --with-applyconfig).
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
|
|
|
|||
|
|
@ -3,111 +3,30 @@
|
|||
package fake
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
v1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
sshpiperv1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned/typed/sshpiper/v1beta1"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
)
|
||||
|
||||
// FakePipes implements PipeInterface
|
||||
type FakePipes struct {
|
||||
// fakePipes implements PipeInterface
|
||||
type fakePipes struct {
|
||||
*gentype.FakeClientWithList[*v1beta1.Pipe, *v1beta1.PipeList]
|
||||
Fake *FakeSshpiperV1beta1
|
||||
ns string
|
||||
}
|
||||
|
||||
var pipesResource = v1beta1.SchemeGroupVersion.WithResource("pipes")
|
||||
|
||||
var pipesKind = v1beta1.SchemeGroupVersion.WithKind("Pipe")
|
||||
|
||||
// Get takes name of the pipe, and returns the corresponding pipe object, and an error if there is any.
|
||||
func (c *FakePipes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Pipe, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(pipesResource, c.ns, name), &v1beta1.Pipe{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
func newFakePipes(fake *FakeSshpiperV1beta1, namespace string) sshpiperv1beta1.PipeInterface {
|
||||
return &fakePipes{
|
||||
gentype.NewFakeClientWithList[*v1beta1.Pipe, *v1beta1.PipeList](
|
||||
fake.Fake,
|
||||
namespace,
|
||||
v1beta1.SchemeGroupVersion.WithResource("pipes"),
|
||||
v1beta1.SchemeGroupVersion.WithKind("Pipe"),
|
||||
func() *v1beta1.Pipe { return &v1beta1.Pipe{} },
|
||||
func() *v1beta1.PipeList { return &v1beta1.PipeList{} },
|
||||
func(dst, src *v1beta1.PipeList) { dst.ListMeta = src.ListMeta },
|
||||
func(list *v1beta1.PipeList) []*v1beta1.Pipe { return gentype.ToPointerSlice(list.Items) },
|
||||
func(list *v1beta1.PipeList, items []*v1beta1.Pipe) { list.Items = gentype.FromPointerSlice(items) },
|
||||
),
|
||||
fake,
|
||||
}
|
||||
return obj.(*v1beta1.Pipe), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Pipes that match those selectors.
|
||||
func (c *FakePipes) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.PipeList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(pipesResource, pipesKind, c.ns, opts), &v1beta1.PipeList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.PipeList{ListMeta: obj.(*v1beta1.PipeList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.PipeList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested pipes.
|
||||
func (c *FakePipes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(pipesResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a pipe and creates it. Returns the server's representation of the pipe, and an error, if there is any.
|
||||
func (c *FakePipes) Create(ctx context.Context, pipe *v1beta1.Pipe, opts v1.CreateOptions) (result *v1beta1.Pipe, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(pipesResource, c.ns, pipe), &v1beta1.Pipe{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Pipe), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a pipe and updates it. Returns the server's representation of the pipe, and an error, if there is any.
|
||||
func (c *FakePipes) Update(ctx context.Context, pipe *v1beta1.Pipe, opts v1.UpdateOptions) (result *v1beta1.Pipe, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(pipesResource, c.ns, pipe), &v1beta1.Pipe{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Pipe), err
|
||||
}
|
||||
|
||||
// Delete takes name of the pipe and deletes it. Returns an error if one occurs.
|
||||
func (c *FakePipes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteActionWithOptions(pipesResource, c.ns, name, opts), &v1beta1.Pipe{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakePipes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(pipesResource, c.ns, listOpts)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.PipeList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched pipe.
|
||||
func (c *FakePipes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.Pipe, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(pipesResource, c.ns, name, pt, data, subresources...), &v1beta1.Pipe{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.Pipe), err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ type FakeSshpiperV1beta1 struct {
|
|||
}
|
||||
|
||||
func (c *FakeSshpiperV1beta1) Pipes(namespace string) v1beta1.PipeInterface {
|
||||
return &FakePipes{c, namespace}
|
||||
return newFakePipes(c, namespace)
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
|
|
|
|||
|
|
@ -3,15 +3,14 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
context "context"
|
||||
|
||||
v1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
sshpiperv1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
scheme "github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
)
|
||||
|
||||
// PipesGetter has a method to return a PipeInterface.
|
||||
|
|
@ -22,141 +21,32 @@ type PipesGetter interface {
|
|||
|
||||
// PipeInterface has methods to work with Pipe resources.
|
||||
type PipeInterface interface {
|
||||
Create(ctx context.Context, pipe *v1beta1.Pipe, opts v1.CreateOptions) (*v1beta1.Pipe, error)
|
||||
Update(ctx context.Context, pipe *v1beta1.Pipe, opts v1.UpdateOptions) (*v1beta1.Pipe, error)
|
||||
Create(ctx context.Context, pipe *sshpiperv1beta1.Pipe, opts v1.CreateOptions) (*sshpiperv1beta1.Pipe, error)
|
||||
Update(ctx context.Context, pipe *sshpiperv1beta1.Pipe, opts v1.UpdateOptions) (*sshpiperv1beta1.Pipe, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*v1beta1.Pipe, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*v1beta1.PipeList, error)
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*sshpiperv1beta1.Pipe, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*sshpiperv1beta1.PipeList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.Pipe, err error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *sshpiperv1beta1.Pipe, err error)
|
||||
PipeExpansion
|
||||
}
|
||||
|
||||
// pipes implements PipeInterface
|
||||
type pipes struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
*gentype.ClientWithList[*sshpiperv1beta1.Pipe, *sshpiperv1beta1.PipeList]
|
||||
}
|
||||
|
||||
// newPipes returns a Pipes
|
||||
func newPipes(c *SshpiperV1beta1Client, namespace string) *pipes {
|
||||
return &pipes{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
gentype.NewClientWithList[*sshpiperv1beta1.Pipe, *sshpiperv1beta1.PipeList](
|
||||
"pipes",
|
||||
c.RESTClient(),
|
||||
scheme.ParameterCodec,
|
||||
namespace,
|
||||
func() *sshpiperv1beta1.Pipe { return &sshpiperv1beta1.Pipe{} },
|
||||
func() *sshpiperv1beta1.PipeList { return &sshpiperv1beta1.PipeList{} },
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the pipe, and returns the corresponding pipe object, and an error if there is any.
|
||||
func (c *pipes) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Pipe, err error) {
|
||||
result = &v1beta1.Pipe{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Pipes that match those selectors.
|
||||
func (c *pipes) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.PipeList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1beta1.PipeList{}
|
||||
err = c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested pipes.
|
||||
func (c *pipes) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch(ctx)
|
||||
}
|
||||
|
||||
// Create takes the representation of a pipe and creates it. Returns the server's representation of the pipe, and an error, if there is any.
|
||||
func (c *pipes) Create(ctx context.Context, pipe *v1beta1.Pipe, opts v1.CreateOptions) (result *v1beta1.Pipe, err error) {
|
||||
result = &v1beta1.Pipe{}
|
||||
err = c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(pipe).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a pipe and updates it. Returns the server's representation of the pipe, and an error, if there is any.
|
||||
func (c *pipes) Update(ctx context.Context, pipe *v1beta1.Pipe, opts v1.UpdateOptions) (result *v1beta1.Pipe, err error) {
|
||||
result = &v1beta1.Pipe{}
|
||||
err = c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
Name(pipe.Name).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(pipe).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the pipe and deletes it. Returns an error if one occurs.
|
||||
func (c *pipes) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
Name(name).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *pipes) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOpts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
VersionedParams(&listOpts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(&opts).
|
||||
Do(ctx).
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched pipe.
|
||||
func (c *pipes) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.Pipe, err error) {
|
||||
result = &v1beta1.Pipe{}
|
||||
err = c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("pipes").
|
||||
Name(name).
|
||||
SubResource(subresources...).
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Body(data).
|
||||
Do(ctx).
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,10 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
http "net/http"
|
||||
|
||||
v1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
"github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned/scheme"
|
||||
sshpiperv1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
scheme "github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
|
|
@ -69,10 +69,10 @@ func New(c rest.Interface) *SshpiperV1beta1Client {
|
|||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta1.SchemeGroupVersion
|
||||
gv := sshpiperv1beta1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
|
||||
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,246 @@
|
|||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
versioned "github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned"
|
||||
internalinterfaces "github.com/tg123/sshpiper/plugin/kubernetes/generated/informers/externalversions/internalinterfaces"
|
||||
sshpiper "github.com/tg123/sshpiper/plugin/kubernetes/generated/informers/externalversions/sshpiper"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client versioned.Interface
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
customResync map[reflect.Type]time.Duration
|
||||
transform cache.TransformFunc
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
// wg tracks how many goroutines were started.
|
||||
wg sync.WaitGroup
|
||||
// shuttingDown is true when Shutdown has been called. It may still be running
|
||||
// because it needs to wait for goroutines.
|
||||
shuttingDown bool
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTransform sets a transform on all informers.
|
||||
func WithTransform(transform cache.TransformFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.transform = transform
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
customResync: make(map[reflect.Type]time.Duration),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.shuttingDown {
|
||||
return
|
||||
}
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
f.wg.Add(1)
|
||||
// We need a new variable in each loop iteration,
|
||||
// otherwise the goroutine would use the loop variable
|
||||
// and that keeps changing.
|
||||
informer := informer
|
||||
go func() {
|
||||
defer f.wg.Done()
|
||||
informer.Run(stopCh)
|
||||
}()
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Shutdown() {
|
||||
f.lock.Lock()
|
||||
f.shuttingDown = true
|
||||
f.lock.Unlock()
|
||||
|
||||
// Will return immediately if there is nothing to wait for.
|
||||
f.wg.Wait()
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
informer.SetTransform(f.transform)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
//
|
||||
// It is typically used like this:
|
||||
//
|
||||
// ctx, cancel := context.Background()
|
||||
// defer cancel()
|
||||
// factory := NewSharedInformerFactory(client, resyncPeriod)
|
||||
// defer factory.WaitForStop() // Returns immediately if nothing was started.
|
||||
// genericInformer := factory.ForResource(resource)
|
||||
// typedInformer := factory.SomeAPIGroup().V1().SomeType()
|
||||
// factory.Start(ctx.Done()) // Start processing these informers.
|
||||
// synced := factory.WaitForCacheSync(ctx.Done())
|
||||
// for v, ok := range synced {
|
||||
// if !ok {
|
||||
// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Creating informers can also be created after Start, but then
|
||||
// // Start must be called again:
|
||||
// anotherGenericInformer := factory.ForResource(resource)
|
||||
// factory.Start(ctx.Done())
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
|
||||
// Start initializes all requested informers. They are handled in goroutines
|
||||
// which run until the stop channel gets closed.
|
||||
// Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync.
|
||||
Start(stopCh <-chan struct{})
|
||||
|
||||
// Shutdown marks a factory as shutting down. At that point no new
|
||||
// informers can be started anymore and Start will return without
|
||||
// doing anything.
|
||||
//
|
||||
// In addition, Shutdown blocks until all goroutines have terminated. For that
|
||||
// to happen, the close channel(s) that they were started with must be closed,
|
||||
// either before Shutdown gets called or while it is waiting.
|
||||
//
|
||||
// Shutdown may be called multiple times, even concurrently. All such calls will
|
||||
// block until all goroutines have terminated.
|
||||
Shutdown()
|
||||
|
||||
// WaitForCacheSync blocks until all started informers' caches were synced
|
||||
// or the stop channel gets closed.
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type.
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
|
||||
// InformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer
|
||||
|
||||
Sshpiper() sshpiper.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Sshpiper() sshpiper.Interface {
|
||||
return sshpiper.New(f, f.namespace, f.tweakListOptions)
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
|
||||
v1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=sshpiper, Version=v1beta1
|
||||
case v1beta1.SchemeGroupVersion.WithResource("pipes"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Sshpiper().V1beta1().Pipes().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
versioned "github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
|
||||
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
|
||||
type TweakListOptionsFunc func(*v1.ListOptions)
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package sshpiper
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/tg123/sshpiper/plugin/kubernetes/generated/informers/externalversions/internalinterfaces"
|
||||
v1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/generated/informers/externalversions/sshpiper/v1beta1"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1beta1 provides access to shared informers for resources in V1beta1.
|
||||
V1beta1() v1beta1.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1beta1 returns a new v1beta1.Interface.
|
||||
func (g *group) V1beta1() v1beta1.Interface {
|
||||
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/tg123/sshpiper/plugin/kubernetes/generated/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// Pipes returns a PipeInformer.
|
||||
Pipes() PipeInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// Pipes returns a PipeInformer.
|
||||
func (v *version) Pipes() PipeInformer {
|
||||
return &pipeInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
time "time"
|
||||
|
||||
apissshpiperv1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
versioned "github.com/tg123/sshpiper/plugin/kubernetes/generated/clientset/versioned"
|
||||
internalinterfaces "github.com/tg123/sshpiper/plugin/kubernetes/generated/informers/externalversions/internalinterfaces"
|
||||
sshpiperv1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/generated/listers/sshpiper/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// PipeInformer provides access to a shared informer and lister for
|
||||
// Pipes.
|
||||
type PipeInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() sshpiperv1beta1.PipeLister
|
||||
}
|
||||
|
||||
type pipeInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewPipeInformer constructs a new informer for Pipe type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewPipeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredPipeInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredPipeInformer constructs a new informer for Pipe type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredPipeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.SshpiperV1beta1().Pipes(namespace).List(context.TODO(), options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.SshpiperV1beta1().Pipes(namespace).Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&apissshpiperv1beta1.Pipe{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *pipeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredPipeInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *pipeInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&apissshpiperv1beta1.Pipe{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *pipeInformer) Lister() sshpiperv1beta1.PipeLister {
|
||||
return sshpiperv1beta1.NewPipeLister(f.Informer().GetIndexer())
|
||||
}
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
v1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
sshpiperv1beta1 "github.com/tg123/sshpiper/plugin/kubernetes/apis/sshpiper/v1beta1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
listers "k8s.io/client-go/listers"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// PipeLister helps list Pipes.
|
||||
|
|
@ -14,7 +14,7 @@ import (
|
|||
type PipeLister interface {
|
||||
// List lists all Pipes in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1beta1.Pipe, err error)
|
||||
List(selector labels.Selector) (ret []*sshpiperv1beta1.Pipe, err error)
|
||||
// Pipes returns an object that can list and get Pipes.
|
||||
Pipes(namespace string) PipeNamespaceLister
|
||||
PipeListerExpansion
|
||||
|
|
@ -22,25 +22,17 @@ type PipeLister interface {
|
|||
|
||||
// pipeLister implements the PipeLister interface.
|
||||
type pipeLister struct {
|
||||
indexer cache.Indexer
|
||||
listers.ResourceIndexer[*sshpiperv1beta1.Pipe]
|
||||
}
|
||||
|
||||
// NewPipeLister returns a new PipeLister.
|
||||
func NewPipeLister(indexer cache.Indexer) PipeLister {
|
||||
return &pipeLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all Pipes in the indexer.
|
||||
func (s *pipeLister) List(selector labels.Selector) (ret []*v1beta1.Pipe, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1beta1.Pipe))
|
||||
})
|
||||
return ret, err
|
||||
return &pipeLister{listers.New[*sshpiperv1beta1.Pipe](indexer, sshpiperv1beta1.Resource("pipe"))}
|
||||
}
|
||||
|
||||
// Pipes returns an object that can list and get Pipes.
|
||||
func (s *pipeLister) Pipes(namespace string) PipeNamespaceLister {
|
||||
return pipeNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
return pipeNamespaceLister{listers.NewNamespaced[*sshpiperv1beta1.Pipe](s.ResourceIndexer, namespace)}
|
||||
}
|
||||
|
||||
// PipeNamespaceLister helps list and get Pipes.
|
||||
|
|
@ -48,36 +40,15 @@ func (s *pipeLister) Pipes(namespace string) PipeNamespaceLister {
|
|||
type PipeNamespaceLister interface {
|
||||
// List lists all Pipes in the indexer for a given namespace.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*v1beta1.Pipe, err error)
|
||||
List(selector labels.Selector) (ret []*sshpiperv1beta1.Pipe, err error)
|
||||
// Get retrieves the Pipe from the indexer for a given namespace and name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*v1beta1.Pipe, error)
|
||||
Get(name string) (*sshpiperv1beta1.Pipe, error)
|
||||
PipeNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// pipeNamespaceLister implements the PipeNamespaceLister
|
||||
// interface.
|
||||
type pipeNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all Pipes in the indexer for a given namespace.
|
||||
func (s pipeNamespaceLister) List(selector labels.Selector) (ret []*v1beta1.Pipe, err error) {
|
||||
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1beta1.Pipe))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the Pipe from the indexer for a given namespace and name.
|
||||
func (s pipeNamespaceLister) Get(name string) (*v1beta1.Pipe, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1beta1.Resource("pipe"), name)
|
||||
}
|
||||
return obj.(*v1beta1.Pipe), nil
|
||||
listers.ResourceIndexer[*sshpiperv1beta1.Pipe]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func (s *skelpipeWrapper) From() []skel.SkelPipeFrom {
|
|||
to: &s.pipe.Spec.To,
|
||||
}
|
||||
|
||||
if f.AuthorizedKeysData != "" || f.AuthorizedKeysFile != "" {
|
||||
if f.AuthorizedKeysData != "" || f.AuthorizedKeysFile != "" || f.AuthorizedKeysSecret.Name != "" {
|
||||
froms = append(froms, &skelpipePublicKeyWrapper{
|
||||
skelpipeFromWrapper: *w,
|
||||
})
|
||||
|
|
@ -171,6 +171,26 @@ func (s *skelpipePublicKeyWrapper) AuthorizedKeys(conn libplugin.ConnMetadata) (
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if s.from.AuthorizedKeysSecret.Name != "" {
|
||||
log.Debugf("mapping to %v authorized keys using secret %v", s.pipe.Spec.To.Host, s.from.AuthorizedKeysSecret.Name)
|
||||
anno := s.pipe.GetAnnotations()
|
||||
|
||||
secret, err := s.plugin.k8sclient.Secrets(s.pipe.Namespace).Get(context.Background(), s.from.AuthorizedKeysSecret.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, k := range []string{anno["sshpiper.com/authorizedkeys_field_name"], anno["authorizedkeys_field_name"], "authorized_keys", "authorizedkeys", "ssh-authorizedkeys"} {
|
||||
data := secret.Data[k]
|
||||
if data != nil {
|
||||
log.Debugf("found authorized keys in secret %v/%v", s.from.AuthorizedKeysSecret.Name, k)
|
||||
byteSlices = append(byteSlices, data)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bytes.Join(byteSlices, []byte("\n")), nil
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +209,7 @@ func (s *skelpipeToPrivateKeyWrapper) PrivateKey(conn libplugin.ConnMetadata) ([
|
|||
var publicKey []byte
|
||||
var privateKey []byte
|
||||
|
||||
for _, k := range []string{anno["privatekey_field_name"], "ssh-privatekey", "privatekey"} {
|
||||
for _, k := range []string{anno["sshpiper.com/privatekey_field_name"], anno["privatekey_field_name"], "ssh-privatekey", "privatekey"} {
|
||||
data := secret.Data[k]
|
||||
if data != nil {
|
||||
log.Debugf("found private key in secret %v/%v", s.to.PrivateKeySecret.Name, k)
|
||||
|
|
@ -198,8 +218,8 @@ func (s *skelpipeToPrivateKeyWrapper) PrivateKey(conn libplugin.ConnMetadata) ([
|
|||
}
|
||||
}
|
||||
|
||||
if anno["no_ca_publickey"] != "true" {
|
||||
for _, k := range []string{anno["publickey_field_name"], "ssh-publickey-cert", "publickey-cert", "ssh-publickey", "publickey"} {
|
||||
if anno["no_ca_publickey"] != "true" && anno["sshpiper.com/no_ca_publickey"] != "true" {
|
||||
for _, k := range []string{anno["sshpiper.com/publickey_field_name"], anno["publickey_field_name"], "ssh-publickey-cert", "publickey-cert", "ssh-publickey", "publickey"} {
|
||||
data := secret.Data[k]
|
||||
if data != nil {
|
||||
log.Debugf("found publickey key cert in secret %v/%v", s.to.PrivateKeySecret.Name, k)
|
||||
|
|
|
|||
|
|
@ -9,18 +9,22 @@ go mod vendor
|
|||
SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")
|
||||
REPO_ROOT=$(realpath "${SCRIPT_ROOT}/../../")
|
||||
CODEGEN_PKG=${REPO_ROOT}/vendor/k8s.io/code-generator
|
||||
THIS_PKG="github.com/tg123/sshpiper/plugin/kubernetes"
|
||||
|
||||
# generate the code with:
|
||||
# --output-base because this script should also be able to run inside the vendor dir of
|
||||
# k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
|
||||
# instead of the $GOPATH directly. For normal projects this can be dropped.
|
||||
# generators deepcopy,client,informer,lister
|
||||
chmod +x "${CODEGEN_PKG}"/kube_codegen.sh
|
||||
"${CODEGEN_PKG}"/kube_codegen.sh \
|
||||
"deepcopy,client,lister" \
|
||||
github.com/tg123/sshpiper/plugin/kubernetes/generated \
|
||||
github.com/tg123/sshpiper/plugin/kubernetes/apis \
|
||||
sshpiper:v1beta1 \
|
||||
--go-header-file /dev/null \
|
||||
--trim-path-prefix github.com/tg123/sshpiper/plugin/kubernetes/
|
||||
|
||||
source "${CODEGEN_PKG}/kube_codegen.sh"
|
||||
|
||||
|
||||
kube::codegen::gen_helpers \
|
||||
--boilerplate /dev/null \
|
||||
"${SCRIPT_ROOT}"
|
||||
|
||||
kube::codegen::gen_register \
|
||||
--boilerplate /dev/null \
|
||||
"${SCRIPT_ROOT}"
|
||||
|
||||
kube::codegen::gen_client \
|
||||
--with-watch \
|
||||
--output-dir "${SCRIPT_ROOT}/generated" \
|
||||
--output-pkg "${THIS_PKG}/generated" \
|
||||
--boilerplate /dev/null \
|
||||
"${SCRIPT_ROOT}/apis"
|
||||
Loading…
Add table
Add a link
Reference in a new issue