-
Notifications
You must be signed in to change notification settings - Fork 125
/
options.go
164 lines (141 loc) · 6.31 KB
/
options.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
Copyright 2018 The Kubernetes 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 options
import (
"fmt"
"io"
"net"
"net/url"
"reflect"
"github.com/spf13/pflag"
oteltrace "go.opentelemetry.io/otel/trace"
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/pkg/apiserver"
generatedopenapi "k8s.io/apiextensions-apiserver/pkg/generated/openapi"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
genericregistry "k8s.io/apiserver/pkg/registry/generic"
genericapiserver "k8s.io/apiserver/pkg/server"
genericoptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/apiserver/pkg/util/openapi"
"k8s.io/apiserver/pkg/util/proxy"
"k8s.io/apiserver/pkg/util/webhook"
scheme "k8s.io/client-go/kubernetes/scheme"
corev1 "k8s.io/client-go/listers/core/v1"
netutils "k8s.io/utils/net"
)
const defaultEtcdPathPrefix = "/registry/apiextensions.kubernetes.io"
// CustomResourceDefinitionsServerOptions describes the runtime options of an apiextensions-apiserver.
type CustomResourceDefinitionsServerOptions struct {
ServerRunOptions *genericoptions.ServerRunOptions
RecommendedOptions *genericoptions.RecommendedOptions
APIEnablement *genericoptions.APIEnablementOptions
StdOut io.Writer
StdErr io.Writer
}
// NewCustomResourceDefinitionsServerOptions creates default options of an apiextensions-apiserver.
func NewCustomResourceDefinitionsServerOptions(out, errOut io.Writer) *CustomResourceDefinitionsServerOptions {
o := &CustomResourceDefinitionsServerOptions{
ServerRunOptions: genericoptions.NewServerRunOptions(),
RecommendedOptions: genericoptions.NewRecommendedOptions(
defaultEtcdPathPrefix,
apiserver.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion, v1.SchemeGroupVersion),
),
APIEnablement: genericoptions.NewAPIEnablementOptions(),
StdOut: out,
StdErr: errOut,
}
return o
}
// AddFlags adds the apiextensions-apiserver flags to the flagset.
func (o CustomResourceDefinitionsServerOptions) AddFlags(fs *pflag.FlagSet) {
o.ServerRunOptions.AddUniversalFlags(fs)
o.RecommendedOptions.AddFlags(fs)
o.APIEnablement.AddFlags(fs)
}
// Validate validates the apiextensions-apiserver options.
func (o CustomResourceDefinitionsServerOptions) Validate() error {
errors := []error{}
errors = append(errors, o.ServerRunOptions.Validate()...)
errors = append(errors, o.RecommendedOptions.Validate()...)
errors = append(errors, o.APIEnablement.Validate(apiserver.Scheme)...)
return utilerrors.NewAggregate(errors)
}
// Complete fills in missing options.
func (o *CustomResourceDefinitionsServerOptions) Complete() error {
return nil
}
// Config returns an apiextensions-apiserver configuration.
func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, error) {
// TODO have a "real" external address
if err := o.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{netutils.ParseIPSloppy("127.0.0.1")}); err != nil {
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
}
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
if err := o.ServerRunOptions.ApplyTo(&serverConfig.Config); err != nil {
return nil, err
}
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
return nil, err
}
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil {
return nil, err
}
crdRESTOptionsGetter, err := NewCRDRESTOptionsGetter(*o.RecommendedOptions.Etcd)
if err != nil {
return nil, err
}
serverConfig.OpenAPIV3Config = genericapiserver.DefaultOpenAPIV3Config(openapi.GetOpenAPIDefinitionsWithoutDisabledFeatures(generatedopenapi.GetOpenAPIDefinitions), openapinamer.NewDefinitionNamer(apiserver.Scheme, scheme.Scheme))
config := &apiserver.Config{
GenericConfig: serverConfig,
ExtraConfig: apiserver.ExtraConfig{
CRDRESTOptionsGetter: crdRESTOptionsGetter,
ServiceResolver: &serviceResolver{serverConfig.SharedInformerFactory.Core().V1().Services().Lister()},
AuthResolverWrapper: webhook.NewDefaultAuthenticationInfoResolverWrapper(nil, nil, serverConfig.LoopbackClientConfig, oteltrace.NewNoopTracerProvider()),
},
}
return config, nil
}
// NewCRDRESTOptionsGetter create a RESTOptionsGetter for CustomResources.
// This works on a copy of the etcd options so we don't mutate originals.
// We assume that the input etcd options have been completed already.
// Avoid messing with anything outside of changes to StorageConfig as that
// may lead to unexpected behavior when the options are applied.
func NewCRDRESTOptionsGetter(etcdOptions genericoptions.EtcdOptions) (genericregistry.RESTOptionsGetter, error) {
etcdOptions.StorageConfig.Codec = unstructured.UnstructuredJSONScheme
etcdOptions.WatchCacheSizes = nil // this control is not provided for custom resources
etcdOptions.SkipHealthEndpoints = true // avoid double wiring of health checks
// creates a generic apiserver config for etcdOptions to mutate
c := genericapiserver.Config{}
if err := etcdOptions.ApplyTo(&c); err != nil {
return nil, err
}
restOptionsGetter := c.RESTOptionsGetter
if restOptionsGetter == nil {
return nil, fmt.Errorf("server.Config RESTOptionsGetter should not be nil")
}
// sanity check that no other fields are set
c.RESTOptionsGetter = nil
if !reflect.DeepEqual(c, genericapiserver.Config{}) {
return nil, fmt.Errorf("only RESTOptionsGetter should have been mutated in server.Config")
}
return restOptionsGetter, nil
}
type serviceResolver struct {
services corev1.ServiceLister
}
func (r *serviceResolver) ResolveEndpoint(namespace, name string, port int32) (*url.URL, error) {
return proxy.ResolveCluster(r.services, namespace, name, port)
}