mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-09-19 14:34:27 +00:00
Allow multiple Pinnipeds to work on same cluster
Yes, this is a huge commit.
The middleware allows you to customize the API groups of all of the
*.pinniped.dev API groups.
Some notes about other small things in this commit:
- We removed the internal/client package in favor of pkg/conciergeclient. The
two packages do basically the same thing. I don't think we use the former
anymore.
- We re-enabled cluster-scoped owner assertions in the integration tests.
This code was added in internal/ownerref. See a0546942 for when this
assertion was removed.
- Note: the middlware code is in charge of restoring the GV of a request object,
so we should never need to write mutations that do that.
- We updated the supervisor secret generation to no longer manually set an owner
reference to the deployment since the middleware code now does this. I think we
still need some way to make an initial event for the secret generator
controller, which involves knowing the namespace and the name of the generated
secret, so I still wired the deployment through. We could use a namespace/name
tuple here, but I was lazy.
Signed-off-by: Andrew Keesler <akeesler@vmware.com>
Co-authored-by: Ryan Richard <richardry@vmware.com>
This commit is contained in:
committed by
Ryan Richard
co-authored by
Ryan Richard
parent
93d25a349f
commit
efe1fa89fe
@@ -10,43 +10,14 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/client-go/pkg/version"
|
||||
|
||||
loginapi "go.pinniped.dev/generated/1.20/apis/concierge/login"
|
||||
loginv1alpha1 "go.pinniped.dev/generated/1.20/apis/concierge/login/v1alpha1"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/registry/credentialrequest"
|
||||
)
|
||||
|
||||
var (
|
||||
//nolint: gochecknoglobals
|
||||
scheme = runtime.NewScheme()
|
||||
//nolint: gochecknoglobals, golint
|
||||
Codecs = serializer.NewCodecFactory(scheme)
|
||||
)
|
||||
|
||||
//nolint: gochecknoinits
|
||||
func init() {
|
||||
utilruntime.Must(loginv1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(loginapi.AddToScheme(scheme))
|
||||
|
||||
// add the options to empty v1
|
||||
metav1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
|
||||
unversioned := schema.GroupVersion{Group: "", Version: "v1"}
|
||||
scheme.AddUnversionedTypes(unversioned,
|
||||
&metav1.Status{},
|
||||
&metav1.APIVersions{},
|
||||
&metav1.APIGroupList{},
|
||||
&metav1.APIGroup{},
|
||||
&metav1.APIResourceList{},
|
||||
)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.RecommendedConfig
|
||||
ExtraConfig ExtraConfig
|
||||
@@ -56,6 +27,9 @@ type ExtraConfig struct {
|
||||
Authenticator credentialrequest.TokenCredentialRequestAuthenticator
|
||||
Issuer credentialrequest.CertIssuer
|
||||
StartControllersPostStartHook func(ctx context.Context)
|
||||
Scheme *runtime.Scheme
|
||||
NegotiatedSerializer runtime.NegotiatedSerializer
|
||||
GroupVersion schema.GroupVersion
|
||||
}
|
||||
|
||||
type PinnipedServer struct {
|
||||
@@ -96,15 +70,15 @@ func (c completedConfig) New() (*PinnipedServer, error) {
|
||||
GenericAPIServer: genericServer,
|
||||
}
|
||||
|
||||
gvr := loginv1alpha1.SchemeGroupVersion.WithResource("tokencredentialrequests")
|
||||
gvr := c.ExtraConfig.GroupVersion.WithResource("tokencredentialrequests")
|
||||
storage := credentialrequest.NewREST(c.ExtraConfig.Authenticator, c.ExtraConfig.Issuer)
|
||||
if err := s.GenericAPIServer.InstallAPIGroup(&genericapiserver.APIGroupInfo{
|
||||
PrioritizedVersions: []schema.GroupVersion{gvr.GroupVersion()},
|
||||
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{gvr.Version: {gvr.Resource: storage}},
|
||||
OptionsExternalVersion: &schema.GroupVersion{Version: "v1"},
|
||||
Scheme: scheme,
|
||||
Scheme: c.ExtraConfig.Scheme,
|
||||
ParameterCodec: metav1.ParameterCodec,
|
||||
NegotiatedSerializer: Codecs,
|
||||
NegotiatedSerializer: c.ExtraConfig.NegotiatedSerializer,
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("could not install API group %s: %w", gvr.String(), err)
|
||||
}
|
||||
|
||||
@@ -11,11 +11,16 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||
|
||||
loginapi "go.pinniped.dev/generated/1.20/apis/concierge/login"
|
||||
loginv1alpha1 "go.pinniped.dev/generated/1.20/apis/concierge/login/v1alpha1"
|
||||
"go.pinniped.dev/internal/apigroup"
|
||||
"go.pinniped.dev/internal/certauthority/dynamiccertauthority"
|
||||
"go.pinniped.dev/internal/concierge/apiserver"
|
||||
"go.pinniped.dev/internal/config/concierge"
|
||||
@@ -23,6 +28,7 @@ import (
|
||||
"go.pinniped.dev/internal/controllermanager"
|
||||
"go.pinniped.dev/internal/downward"
|
||||
"go.pinniped.dev/internal/dynamiccert"
|
||||
"go.pinniped.dev/internal/groupsuffix"
|
||||
"go.pinniped.dev/internal/here"
|
||||
"go.pinniped.dev/internal/plog"
|
||||
"go.pinniped.dev/internal/registry/credentialrequest"
|
||||
@@ -168,24 +174,80 @@ func getAggregatedAPIServerConfig(
|
||||
startControllersPostStartHook func(context.Context),
|
||||
apiGroupSuffix string,
|
||||
) (*apiserver.Config, error) {
|
||||
// This is ignored for now because we turn off etcd storage below, but this is
|
||||
// the right prefix in case we turn it back on.
|
||||
apiGroup, ok := apigroup.Make(loginv1alpha1.GroupName, apiGroupSuffix)
|
||||
apiGroup, ok := groupsuffix.Replace(loginv1alpha1.GroupName, apiGroupSuffix)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("cannot make api group from %s/%s", loginv1alpha1.GroupName, apiGroupSuffix)
|
||||
}
|
||||
|
||||
// standard set up of the server side scheme
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
|
||||
utilruntime.Must(loginv1alpha1.AddToScheme(scheme))
|
||||
utilruntime.Must(loginapi.AddToScheme(scheme))
|
||||
|
||||
// add the options to empty v1
|
||||
metav1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
|
||||
unversioned := schema.GroupVersion{Group: "", Version: "v1"}
|
||||
scheme.AddUnversionedTypes(unversioned,
|
||||
&metav1.Status{},
|
||||
&metav1.APIVersions{},
|
||||
&metav1.APIGroupList{},
|
||||
&metav1.APIGroup{},
|
||||
&metav1.APIResourceList{},
|
||||
)
|
||||
|
||||
// use closure to avoid mutating scheme during iteration
|
||||
var addPinnipedTypeToAPIGroup []func() //nolint: prealloc // expected slice size is unknown
|
||||
for gvk := range scheme.AllKnownTypes() {
|
||||
gvk := gvk
|
||||
|
||||
if apiGroup == loginv1alpha1.GroupName {
|
||||
break // bail out early if using the standard group
|
||||
}
|
||||
|
||||
if gvk.Group != loginv1alpha1.GroupName {
|
||||
continue // ignore types that are not in the aggregated API group
|
||||
}
|
||||
|
||||
// re-register the existing type but with the new group
|
||||
f := func() {
|
||||
obj, err := scheme.New(gvk)
|
||||
if err != nil {
|
||||
panic(err) // programmer error, scheme internal code is broken
|
||||
}
|
||||
newGVK := schema.GroupVersionKind{
|
||||
Group: apiGroup,
|
||||
Version: gvk.Version,
|
||||
Kind: gvk.Kind,
|
||||
}
|
||||
scheme.AddKnownTypeWithName(newGVK, obj)
|
||||
}
|
||||
|
||||
addPinnipedTypeToAPIGroup = append(addPinnipedTypeToAPIGroup, f)
|
||||
}
|
||||
|
||||
// run the closures to mutate the scheme to understand the types at the new group
|
||||
for _, f := range addPinnipedTypeToAPIGroup {
|
||||
f()
|
||||
}
|
||||
|
||||
defaultEtcdPathPrefix := fmt.Sprintf("/registry/%s", apiGroup)
|
||||
groupVersion := schema.GroupVersion{
|
||||
Group: apiGroup,
|
||||
Version: loginv1alpha1.SchemeGroupVersion.Version,
|
||||
}
|
||||
|
||||
recommendedOptions := genericoptions.NewRecommendedOptions(
|
||||
defaultEtcdPathPrefix,
|
||||
apiserver.Codecs.LegacyCodec(loginv1alpha1.SchemeGroupVersion),
|
||||
// TODO we should check to see if all the other default settings are acceptable for us
|
||||
codecs.LegacyCodec(groupVersion),
|
||||
)
|
||||
recommendedOptions.Etcd = nil // turn off etcd storage because we don't need it yet
|
||||
recommendedOptions.SecureServing.ServerCert.GeneratedCert = dynamicCertProvider
|
||||
recommendedOptions.SecureServing.BindPort = 8443 // Don't run on default 443 because that requires root
|
||||
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(codecs)
|
||||
// Note that among other things, this ApplyTo() function copies
|
||||
// `recommendedOptions.SecureServing.ServerCert.GeneratedCert` into
|
||||
// `serverConfig.SecureServing.Cert` thus making `dynamicCertProvider`
|
||||
@@ -205,6 +267,9 @@ func getAggregatedAPIServerConfig(
|
||||
Authenticator: authenticator,
|
||||
Issuer: issuer,
|
||||
StartControllersPostStartHook: startControllersPostStartHook,
|
||||
Scheme: scheme,
|
||||
NegotiatedSerializer: codecs,
|
||||
GroupVersion: groupVersion,
|
||||
},
|
||||
}
|
||||
return apiServerConfig, nil
|
||||
|
||||
Reference in New Issue
Block a user