2020-07-23 15:05:21 +00:00
/ *
Copyright 2020 VMware , Inc .
SPDX - License - Identifier : Apache - 2.0
* /
package apiserver
import (
2020-07-31 16:08:07 +00:00
"context"
2020-07-23 15:05:21 +00:00
"fmt"
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/authentication/authenticator"
"k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server"
"k8s.io/client-go/pkg/version"
"k8s.io/klog/v2"
2020-08-24 19:30:45 +00:00
pinnipedapi "github.com/suzerain-io/pinniped/generated/1.19/apis/pinniped"
pinnipedv1alpha1 "github.com/suzerain-io/pinniped/generated/1.19/apis/pinniped/v1alpha1"
2020-08-20 17:54:15 +00:00
"github.com/suzerain-io/pinniped/internal/registry/credentialrequest"
2020-07-23 15:05:21 +00:00
)
var (
//nolint: gochecknoglobals
scheme = runtime . NewScheme ( )
//nolint: gochecknoglobals
//nolint: golint
Codecs = serializer . NewCodecFactory ( scheme )
)
//nolint: gochecknoinits
func init ( ) {
2020-08-20 17:54:15 +00:00
utilruntime . Must ( pinnipedv1alpha1 . AddToScheme ( scheme ) )
utilruntime . Must ( pinnipedapi . AddToScheme ( scheme ) )
2020-07-23 15:05:21 +00:00
// 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
}
type ExtraConfig struct {
2020-07-31 16:08:07 +00:00
Webhook authenticator . Token
2020-08-14 14:11:14 +00:00
Issuer credentialrequest . CertIssuer
2020-07-31 16:08:07 +00:00
StartControllersPostStartHook func ( ctx context . Context )
2020-07-23 15:05:21 +00:00
}
2020-08-20 17:54:15 +00:00
type PinnipedServer struct {
2020-07-23 15:05:21 +00:00
GenericAPIServer * genericapiserver . GenericAPIServer
}
type completedConfig struct {
GenericConfig genericapiserver . CompletedConfig
ExtraConfig * ExtraConfig
}
type CompletedConfig struct {
// Embed a private pointer that cannot be instantiated outside of this package.
* completedConfig
}
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
func ( c * Config ) Complete ( ) CompletedConfig {
completedCfg := completedConfig {
c . GenericConfig . Complete ( ) ,
& c . ExtraConfig ,
}
versionInfo := version . Get ( )
completedCfg . GenericConfig . Version = & versionInfo
return CompletedConfig { completedConfig : & completedCfg }
}
// New returns a new instance of AdmissionServer from the given config.
2020-08-20 17:54:15 +00:00
func ( c completedConfig ) New ( ) ( * PinnipedServer , error ) {
genericServer , err := c . GenericConfig . New ( "pinniped-server" , genericapiserver . NewEmptyDelegate ( ) ) // completion is done in Complete, no need for a second time
2020-07-23 15:05:21 +00:00
if err != nil {
return nil , fmt . Errorf ( "completion error: %w" , err )
}
2020-08-20 17:54:15 +00:00
s := & PinnipedServer {
2020-07-23 15:05:21 +00:00
GenericAPIServer : genericServer ,
}
2020-08-20 17:54:15 +00:00
gvr := pinnipedv1alpha1 . SchemeGroupVersion . WithResource ( "credentialrequests" )
2020-07-23 15:05:21 +00:00
apiGroupInfo := genericapiserver . APIGroupInfo {
PrioritizedVersions : [ ] schema . GroupVersion { gvr . GroupVersion ( ) } ,
VersionedResourcesStorageMap : map [ string ] map [ string ] rest . Storage { } ,
OptionsExternalVersion : & schema . GroupVersion { Version : "v1" } ,
Scheme : scheme ,
ParameterCodec : metav1 . ParameterCodec ,
NegotiatedSerializer : Codecs ,
}
2020-08-14 14:11:14 +00:00
credentialRequestStorage := credentialrequest . NewREST ( c . ExtraConfig . Webhook , c . ExtraConfig . Issuer )
2020-07-23 15:05:21 +00:00
v1alpha1Storage , ok := apiGroupInfo . VersionedResourcesStorageMap [ gvr . Version ]
if ! ok {
v1alpha1Storage = map [ string ] rest . Storage { }
}
2020-08-14 14:11:14 +00:00
v1alpha1Storage [ gvr . Resource ] = credentialRequestStorage
2020-07-23 15:05:21 +00:00
apiGroupInfo . VersionedResourcesStorageMap [ gvr . Version ] = v1alpha1Storage
if err := s . GenericAPIServer . InstallAPIGroup ( & apiGroupInfo ) ; err != nil {
return nil , fmt . Errorf ( "install API group error: %w" , err )
}
2020-07-31 16:08:07 +00:00
s . GenericAPIServer . AddPostStartHookOrDie ( "start-controllers" ,
func ( postStartContext genericapiserver . PostStartHookContext ) error {
2020-07-31 21:35:20 +00:00
klog . InfoS ( "start-controllers post start hook starting" )
2020-07-31 16:08:07 +00:00
ctx , cancel := context . WithCancel ( context . Background ( ) )
go func ( ) {
<- postStartContext . StopCh
cancel ( )
} ( )
c . ExtraConfig . StartControllersPostStartHook ( ctx )
2020-07-23 15:05:21 +00:00
return nil
} ,
)
return s , nil
}