mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-06-10 10:15:57 +00:00
vendor: revendor metrics-server, custom-metrics-apiserver
This commit is contained in:
parent
752ce84723
commit
523aa52367
1010 changed files with 91458 additions and 29107 deletions
100
vendor/k8s.io/apiserver/pkg/server/options/audit.go
generated
vendored
100
vendor/k8s.io/apiserver/pkg/server/options/audit.go
generated
vendored
|
|
@ -25,9 +25,8 @@ import (
|
|||
|
||||
"github.com/spf13/pflag"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
auditinternal "k8s.io/apiserver/pkg/apis/audit"
|
||||
|
|
@ -36,20 +35,12 @@ import (
|
|||
auditv1beta1 "k8s.io/apiserver/pkg/apis/audit/v1beta1"
|
||||
"k8s.io/apiserver/pkg/audit"
|
||||
"k8s.io/apiserver/pkg/audit/policy"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/server/egressselector"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
pluginbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
|
||||
plugindynamic "k8s.io/apiserver/plugin/pkg/audit/dynamic"
|
||||
pluginenforced "k8s.io/apiserver/plugin/pkg/audit/dynamic/enforced"
|
||||
pluginlog "k8s.io/apiserver/plugin/pkg/audit/log"
|
||||
plugintruncate "k8s.io/apiserver/plugin/pkg/audit/truncate"
|
||||
pluginwebhook "k8s.io/apiserver/plugin/pkg/audit/webhook"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -80,7 +71,6 @@ type AuditOptions struct {
|
|||
// Plugin options
|
||||
LogOptions AuditLogOptions
|
||||
WebhookOptions AuditWebhookOptions
|
||||
DynamicOptions AuditDynamicOptions
|
||||
}
|
||||
|
||||
const (
|
||||
|
|
@ -180,10 +170,6 @@ func NewAuditOptions() *AuditOptions {
|
|||
TruncateOptions: NewAuditTruncateOptions(),
|
||||
GroupVersionString: "audit.k8s.io/v1",
|
||||
},
|
||||
DynamicOptions: AuditDynamicOptions{
|
||||
Enabled: false,
|
||||
BatchConfig: plugindynamic.NewDefaultWebhookBatchConfig(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -206,7 +192,6 @@ func (o *AuditOptions) Validate() []error {
|
|||
var allErrors []error
|
||||
allErrors = append(allErrors, o.LogOptions.Validate()...)
|
||||
allErrors = append(allErrors, o.WebhookOptions.Validate()...)
|
||||
allErrors = append(allErrors, o.DynamicOptions.Validate()...)
|
||||
|
||||
return allErrors
|
||||
}
|
||||
|
|
@ -286,15 +271,10 @@ func (o *AuditOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
o.WebhookOptions.AddFlags(fs)
|
||||
o.WebhookOptions.BatchOptions.AddFlags(pluginwebhook.PluginName, fs)
|
||||
o.WebhookOptions.TruncateOptions.AddFlags(pluginwebhook.PluginName, fs)
|
||||
o.DynamicOptions.AddFlags(fs)
|
||||
}
|
||||
|
||||
func (o *AuditOptions) ApplyTo(
|
||||
c *server.Config,
|
||||
kubeClientConfig *restclient.Config,
|
||||
informers informers.SharedInformerFactory,
|
||||
processInfo *ProcessInfo,
|
||||
webhookOptions *WebhookOptions,
|
||||
) error {
|
||||
if o == nil {
|
||||
return nil
|
||||
|
|
@ -347,23 +327,7 @@ func (o *AuditOptions) ApplyTo(
|
|||
|
||||
// 4. Apply dynamic options.
|
||||
var dynamicBackend audit.Backend
|
||||
if o.DynamicOptions.enabled() {
|
||||
// if dynamic is enabled the webhook and log backends need to be wrapped in an enforced backend with the static policy
|
||||
if webhookBackend != nil {
|
||||
webhookBackend = pluginenforced.NewBackend(webhookBackend, checker)
|
||||
}
|
||||
if logBackend != nil {
|
||||
logBackend = pluginenforced.NewBackend(logBackend, checker)
|
||||
}
|
||||
// build dynamic backend
|
||||
dynamicBackend, checker, err = o.DynamicOptions.newBackend(c.ExternalAddress, kubeClientConfig, informers, processInfo, webhookOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// union dynamic and webhook backends so that truncate options can be applied to both
|
||||
dynamicBackend = appendBackend(webhookBackend, dynamicBackend)
|
||||
dynamicBackend = o.WebhookOptions.TruncateOptions.wrapBackend(dynamicBackend, groupVersion)
|
||||
} else if webhookBackend != nil {
|
||||
if webhookBackend != nil {
|
||||
// if only webhook is enabled wrap it in the truncate options
|
||||
dynamicBackend = o.WebhookOptions.TruncateOptions.wrapBackend(webhookBackend, groupVersion)
|
||||
}
|
||||
|
|
@ -610,66 +574,6 @@ func (o *AuditWebhookOptions) newUntruncatedBackend(customDial utilnet.DialFunc)
|
|||
return webhook, nil
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&o.Enabled, "audit-dynamic-configuration", o.Enabled,
|
||||
"Enables dynamic audit configuration. This feature also requires the DynamicAuditing feature flag")
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) enabled() bool {
|
||||
return o.Enabled && utilfeature.DefaultFeatureGate.Enabled(features.DynamicAuditing)
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) Validate() []error {
|
||||
var allErrors []error
|
||||
if o.Enabled && !utilfeature.DefaultFeatureGate.Enabled(features.DynamicAuditing) {
|
||||
allErrors = append(allErrors, fmt.Errorf("--audit-dynamic-configuration set, but DynamicAuditing feature gate is not enabled"))
|
||||
}
|
||||
return allErrors
|
||||
}
|
||||
|
||||
func (o *AuditDynamicOptions) newBackend(
|
||||
hostname string,
|
||||
kubeClientConfig *restclient.Config,
|
||||
informers informers.SharedInformerFactory,
|
||||
processInfo *ProcessInfo,
|
||||
webhookOptions *WebhookOptions,
|
||||
) (audit.Backend, policy.Checker, error) {
|
||||
if err := validateProcessInfo(processInfo); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(kubeClientConfig)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if webhookOptions == nil {
|
||||
webhookOptions = NewWebhookOptions()
|
||||
}
|
||||
checker := policy.NewDynamicChecker()
|
||||
informer := informers.Auditregistration().V1alpha1().AuditSinks()
|
||||
eventSink := &v1core.EventSinkImpl{Interface: clientset.CoreV1().Events(processInfo.Namespace)}
|
||||
|
||||
dc := &plugindynamic.Config{
|
||||
Informer: informer,
|
||||
BufferedConfig: o.BatchConfig,
|
||||
EventConfig: plugindynamic.EventConfig{
|
||||
Sink: eventSink,
|
||||
Source: corev1.EventSource{
|
||||
Component: processInfo.Name,
|
||||
Host: hostname,
|
||||
},
|
||||
},
|
||||
WebhookConfig: plugindynamic.WebhookConfig{
|
||||
AuthInfoResolverWrapper: webhookOptions.AuthInfoResolverWrapper,
|
||||
ServiceResolver: webhookOptions.ServiceResolver,
|
||||
},
|
||||
}
|
||||
backend, err := plugindynamic.NewBackend(dc)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not create dynamic audit backend: %v", err)
|
||||
}
|
||||
return backend, checker, nil
|
||||
}
|
||||
|
||||
// defaultWebhookBatchConfig returns the default BatchConfig used by the Webhook backend.
|
||||
func defaultWebhookBatchConfig() pluginbuffered.BatchConfig {
|
||||
return pluginbuffered.BatchConfig{
|
||||
|
|
|
|||
60
vendor/k8s.io/apiserver/pkg/server/options/authentication.go
generated
vendored
60
vendor/k8s.io/apiserver/pkg/server/options/authentication.go
generated
vendored
|
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||
package options
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -27,7 +25,6 @@ import (
|
|||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apiserver/pkg/authentication/authenticatorfactory"
|
||||
"k8s.io/apiserver/pkg/authentication/request/headerrequest"
|
||||
|
|
@ -35,7 +32,7 @@ import (
|
|||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||
)
|
||||
|
||||
|
|
@ -319,7 +316,6 @@ func (s *DelegatingAuthenticationOptions) ApplyTo(authenticationInfo *server.Aut
|
|||
if openAPIConfig != nil {
|
||||
openAPIConfig.SecurityDefinitions = securityDefinitions
|
||||
}
|
||||
authenticationInfo.SupportsBasicAuth = false
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -331,66 +327,28 @@ const (
|
|||
// by --requestheader-username-headers. This is created in the cluster by the kube-apiserver.
|
||||
// "WARNING: generally do not depend on authorization being already done for incoming requests.")
|
||||
authenticationConfigMapName = "extension-apiserver-authentication"
|
||||
authenticationRoleName = "extension-apiserver-authentication-reader"
|
||||
)
|
||||
|
||||
func (s *DelegatingAuthenticationOptions) createRequestHeaderConfig(client kubernetes.Interface) (*authenticatorfactory.RequestHeaderConfig, error) {
|
||||
requestHeaderCAProvider, err := dynamiccertificates.NewDynamicCAFromConfigMapController("client-ca", authenticationConfigMapNamespace, authenticationConfigMapName, "requestheader-client-ca-file", client)
|
||||
dynamicRequestHeaderProvider, err := newDynamicRequestHeaderController(client)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create request header authentication config: %v", err)
|
||||
}
|
||||
|
||||
authConfigMap, err := client.CoreV1().ConfigMaps(authenticationConfigMapNamespace).Get(context.TODO(), authenticationConfigMapName, metav1.GetOptions{})
|
||||
switch {
|
||||
case errors.IsNotFound(err):
|
||||
// ignore, authConfigMap is nil now
|
||||
return nil, nil
|
||||
case errors.IsForbidden(err):
|
||||
klog.Warningf("Unable to get configmap/%s in %s. Usually fixed by "+
|
||||
"'kubectl create rolebinding -n %s ROLEBINDING_NAME --role=%s --serviceaccount=YOUR_NS:YOUR_SA'",
|
||||
authenticationConfigMapName, authenticationConfigMapNamespace, authenticationConfigMapNamespace, authenticationRoleName)
|
||||
return nil, err
|
||||
case err != nil:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
usernameHeaders, err := deserializeStrings(authConfigMap.Data["requestheader-username-headers"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
groupHeaders, err := deserializeStrings(authConfigMap.Data["requestheader-group-headers"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extraHeaderPrefixes, err := deserializeStrings(authConfigMap.Data["requestheader-extra-headers-prefix"])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
allowedNames, err := deserializeStrings(authConfigMap.Data["requestheader-allowed-names"])
|
||||
if err != nil {
|
||||
// look up authentication configuration in the cluster and in case of an err defer to authentication-tolerate-lookup-failure flag
|
||||
if err := dynamicRequestHeaderProvider.RunOnce(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &authenticatorfactory.RequestHeaderConfig{
|
||||
CAContentProvider: requestHeaderCAProvider,
|
||||
UsernameHeaders: headerrequest.StaticStringSlice(usernameHeaders),
|
||||
GroupHeaders: headerrequest.StaticStringSlice(groupHeaders),
|
||||
ExtraHeaderPrefixes: headerrequest.StaticStringSlice(extraHeaderPrefixes),
|
||||
AllowedClientNames: headerrequest.StaticStringSlice(allowedNames),
|
||||
CAContentProvider: dynamicRequestHeaderProvider,
|
||||
UsernameHeaders: headerrequest.StringSliceProvider(headerrequest.StringSliceProviderFunc(dynamicRequestHeaderProvider.UsernameHeaders)),
|
||||
GroupHeaders: headerrequest.StringSliceProvider(headerrequest.StringSliceProviderFunc(dynamicRequestHeaderProvider.GroupHeaders)),
|
||||
ExtraHeaderPrefixes: headerrequest.StringSliceProvider(headerrequest.StringSliceProviderFunc(dynamicRequestHeaderProvider.ExtraHeaderPrefixes)),
|
||||
AllowedClientNames: headerrequest.StringSliceProvider(headerrequest.StringSliceProviderFunc(dynamicRequestHeaderProvider.AllowedClientNames)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func deserializeStrings(in string) ([]string, error) {
|
||||
if len(in) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
var ret []string
|
||||
if err := json.Unmarshal([]byte(in), &ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// getClient returns a Kubernetes clientset. If s.RemoteKubeConfigFileOptional is true, nil will be returned
|
||||
// if no kubeconfig is specified by the user and the in-cluster config is not found.
|
||||
func (s *DelegatingAuthenticationOptions) getClient() (kubernetes.Interface, error) {
|
||||
|
|
|
|||
79
vendor/k8s.io/apiserver/pkg/server/options/authentication_dynamic_request_header.go
generated
vendored
Normal file
79
vendor/k8s.io/apiserver/pkg/server/options/authentication_dynamic_request_header.go
generated
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
Copyright 2020 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"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/authentication/request/headerrequest"
|
||||
"k8s.io/apiserver/pkg/server/dynamiccertificates"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
var _ dynamiccertificates.ControllerRunner = &DynamicRequestHeaderController{}
|
||||
var _ dynamiccertificates.Notifier = &DynamicRequestHeaderController{}
|
||||
var _ dynamiccertificates.CAContentProvider = &DynamicRequestHeaderController{}
|
||||
|
||||
var _ headerrequest.RequestHeaderAuthRequestProvider = &DynamicRequestHeaderController{}
|
||||
|
||||
// DynamicRequestHeaderController combines DynamicCAFromConfigMapController and RequestHeaderAuthRequestController
|
||||
// into one controller for dynamically filling RequestHeaderConfig struct
|
||||
type DynamicRequestHeaderController struct {
|
||||
*dynamiccertificates.ConfigMapCAController
|
||||
*headerrequest.RequestHeaderAuthRequestController
|
||||
}
|
||||
|
||||
// newDynamicRequestHeaderController creates a new controller that implements DynamicRequestHeaderController
|
||||
func newDynamicRequestHeaderController(client kubernetes.Interface) (*DynamicRequestHeaderController, error) {
|
||||
requestHeaderCAController, err := dynamiccertificates.NewDynamicCAFromConfigMapController(
|
||||
"client-ca",
|
||||
authenticationConfigMapNamespace,
|
||||
authenticationConfigMapName,
|
||||
"requestheader-client-ca-file",
|
||||
client)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create DynamicCAFromConfigMap controller: %v", err)
|
||||
}
|
||||
|
||||
requestHeaderAuthRequestController := headerrequest.NewRequestHeaderAuthRequestController(
|
||||
authenticationConfigMapName,
|
||||
authenticationConfigMapNamespace,
|
||||
client,
|
||||
"requestheader-username-headers",
|
||||
"requestheader-group-headers",
|
||||
"requestheader-extra-headers-prefix",
|
||||
"requestheader-allowed-names",
|
||||
)
|
||||
return &DynamicRequestHeaderController{
|
||||
ConfigMapCAController: requestHeaderCAController,
|
||||
RequestHeaderAuthRequestController: requestHeaderAuthRequestController,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *DynamicRequestHeaderController) RunOnce() error {
|
||||
errs := []error{}
|
||||
errs = append(errs, c.ConfigMapCAController.RunOnce())
|
||||
errs = append(errs, c.RequestHeaderAuthRequestController.RunOnce())
|
||||
return errors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
func (c *DynamicRequestHeaderController) Run(workers int, stopCh <-chan struct{}) {
|
||||
go c.ConfigMapCAController.Run(workers, stopCh)
|
||||
go c.RequestHeaderAuthRequestController.Run(workers, stopCh)
|
||||
<-stopCh
|
||||
}
|
||||
2
vendor/k8s.io/apiserver/pkg/server/options/authorization.go
generated
vendored
2
vendor/k8s.io/apiserver/pkg/server/options/authorization.go
generated
vendored
|
|
@ -21,7 +21,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizerfactory"
|
||||
|
|
|
|||
4
vendor/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go
generated
vendored
4
vendor/k8s.io/apiserver/pkg/server/options/deprecated_insecure_serving.go
generated
vendored
|
|
@ -43,7 +43,7 @@ type DeprecatedInsecureServingOptions struct {
|
|||
|
||||
// ListenFunc can be overridden to create a custom listener, e.g. for mocking in tests.
|
||||
// It defaults to options.CreateListener.
|
||||
ListenFunc func(network, addr string) (net.Listener, int, error)
|
||||
ListenFunc func(network, addr string, config net.ListenConfig) (net.Listener, int, error)
|
||||
}
|
||||
|
||||
// Validate ensures that the insecure port values within the range of the port.
|
||||
|
|
@ -113,7 +113,7 @@ func (s *DeprecatedInsecureServingOptions) ApplyTo(c **server.DeprecatedInsecure
|
|||
listen = s.ListenFunc
|
||||
}
|
||||
addr := net.JoinHostPort(s.BindAddress.String(), fmt.Sprintf("%d", s.BindPort))
|
||||
s.Listener, s.BindPort, err = listen(s.BindNetwork, addr)
|
||||
s.Listener, s.BindPort, err = listen(s.BindNetwork, addr, net.ListenConfig{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create listener: %v", err)
|
||||
}
|
||||
|
|
|
|||
33
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/config.go
generated
vendored
33
vendor/k8s.io/apiserver/pkg/server/options/encryptionconfig/config.go
generated
vendored
|
|
@ -161,15 +161,14 @@ func GetTransformerOverrides(filepath string) (map[schema.GroupResource]value.Tr
|
|||
}
|
||||
defer f.Close()
|
||||
|
||||
result, err := ParseEncryptionConfiguration(f)
|
||||
result, err := parseEncryptionConfiguration(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error while parsing encryption provider configuration file %q: %v", filepath, err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// ParseEncryptionConfiguration parses configuration data and returns the transformer overrides
|
||||
func ParseEncryptionConfiguration(f io.Reader) (map[schema.GroupResource]value.Transformer, error) {
|
||||
func parseEncryptionConfiguration(f io.Reader) (map[schema.GroupResource]value.Transformer, error) {
|
||||
configFileContents, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not read contents: %v", err)
|
||||
|
|
@ -184,7 +183,7 @@ func ParseEncryptionConfiguration(f io.Reader) (map[schema.GroupResource]value.T
|
|||
|
||||
// For each entry in the configuration
|
||||
for _, resourceConfig := range config.Resources {
|
||||
transformers, err := GetPrefixTransformers(&resourceConfig)
|
||||
transformers, err := prefixTransformers(&resourceConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -205,7 +204,6 @@ func ParseEncryptionConfiguration(f io.Reader) (map[schema.GroupResource]value.T
|
|||
|
||||
}
|
||||
|
||||
// loadConfig decodes data as a EncryptionConfiguration object.
|
||||
func loadConfig(data []byte) (*apiserverconfig.EncryptionConfiguration, error) {
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
|
|
@ -227,8 +225,7 @@ func loadConfig(data []byte) (*apiserverconfig.EncryptionConfiguration, error) {
|
|||
// The factory to create kms service. This is to make writing test easier.
|
||||
var envelopeServiceFactory = envelope.NewGRPCService
|
||||
|
||||
// GetPrefixTransformers constructs and returns the appropriate prefix transformers for the passed resource using its configuration.
|
||||
func GetPrefixTransformers(config *apiserverconfig.ResourceConfiguration) ([]value.PrefixTransformer, error) {
|
||||
func prefixTransformers(config *apiserverconfig.ResourceConfiguration) ([]value.PrefixTransformer, error) {
|
||||
var result []value.PrefixTransformer
|
||||
for _, provider := range config.Providers {
|
||||
var (
|
||||
|
|
@ -238,18 +235,18 @@ func GetPrefixTransformers(config *apiserverconfig.ResourceConfiguration) ([]val
|
|||
|
||||
switch {
|
||||
case provider.AESGCM != nil:
|
||||
transformer, err = GetAESPrefixTransformer(provider.AESGCM, aestransformer.NewGCMTransformer, aesGCMTransformerPrefixV1)
|
||||
transformer, err = aesPrefixTransformer(provider.AESGCM, aestransformer.NewGCMTransformer, aesGCMTransformerPrefixV1)
|
||||
case provider.AESCBC != nil:
|
||||
transformer, err = GetAESPrefixTransformer(provider.AESCBC, aestransformer.NewCBCTransformer, aesCBCTransformerPrefixV1)
|
||||
transformer, err = aesPrefixTransformer(provider.AESCBC, aestransformer.NewCBCTransformer, aesCBCTransformerPrefixV1)
|
||||
case provider.Secretbox != nil:
|
||||
transformer, err = GetSecretboxPrefixTransformer(provider.Secretbox)
|
||||
transformer, err = secretboxPrefixTransformer(provider.Secretbox)
|
||||
case provider.KMS != nil:
|
||||
envelopeService, err := envelopeServiceFactory(provider.KMS.Endpoint, provider.KMS.Timeout.Duration)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not configure KMS plugin %q, error: %v", provider.KMS.Name, err)
|
||||
}
|
||||
|
||||
transformer, err = getEnvelopePrefixTransformer(provider.KMS, envelopeService, kmsTransformerPrefixV1)
|
||||
transformer, err = envelopePrefixTransformer(provider.KMS, envelopeService, kmsTransformerPrefixV1)
|
||||
case provider.Identity != nil:
|
||||
transformer = value.PrefixTransformer{
|
||||
Transformer: identity.NewEncryptCheckTransformer(),
|
||||
|
|
@ -267,12 +264,9 @@ func GetPrefixTransformers(config *apiserverconfig.ResourceConfiguration) ([]val
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// BlockTransformerFunc takes an AES cipher block and returns a value transformer.
|
||||
type BlockTransformerFunc func(cipher.Block) value.Transformer
|
||||
type blockTransformerFunc func(cipher.Block) value.Transformer
|
||||
|
||||
// GetAESPrefixTransformer returns a prefix transformer from the provided configuration.
|
||||
// Returns an AES transformer based on the provided prefix and block transformer.
|
||||
func GetAESPrefixTransformer(config *apiserverconfig.AESConfiguration, fn BlockTransformerFunc, prefix string) (value.PrefixTransformer, error) {
|
||||
func aesPrefixTransformer(config *apiserverconfig.AESConfiguration, fn blockTransformerFunc, prefix string) (value.PrefixTransformer, error) {
|
||||
var result value.PrefixTransformer
|
||||
|
||||
if len(config.Keys) == 0 {
|
||||
|
|
@ -319,8 +313,7 @@ func GetAESPrefixTransformer(config *apiserverconfig.AESConfiguration, fn BlockT
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// GetSecretboxPrefixTransformer returns a prefix transformer from the provided configuration
|
||||
func GetSecretboxPrefixTransformer(config *apiserverconfig.SecretboxConfiguration) (value.PrefixTransformer, error) {
|
||||
func secretboxPrefixTransformer(config *apiserverconfig.SecretboxConfiguration) (value.PrefixTransformer, error) {
|
||||
var result value.PrefixTransformer
|
||||
|
||||
if len(config.Keys) == 0 {
|
||||
|
|
@ -370,9 +363,7 @@ func GetSecretboxPrefixTransformer(config *apiserverconfig.SecretboxConfiguratio
|
|||
return result, nil
|
||||
}
|
||||
|
||||
// getEnvelopePrefixTransformer returns a prefix transformer from the provided config.
|
||||
// envelopeService is used as the root of trust.
|
||||
func getEnvelopePrefixTransformer(config *apiserverconfig.KMSConfiguration, envelopeService envelope.Service, prefix string) (value.PrefixTransformer, error) {
|
||||
func envelopePrefixTransformer(config *apiserverconfig.KMSConfiguration, envelopeService envelope.Service, prefix string) (value.PrefixTransformer, error) {
|
||||
envelopeTransformer, err := envelope.NewEnvelopeTransformer(envelopeService, int(*config.CacheSize), aestransformer.NewCBCTransformer)
|
||||
if err != nil {
|
||||
return value.PrefixTransformer{}, err
|
||||
|
|
|
|||
30
vendor/k8s.io/apiserver/pkg/server/options/etcd.go
generated
vendored
30
vendor/k8s.io/apiserver/pkg/server/options/etcd.go
generated
vendored
|
|
@ -35,6 +35,7 @@ import (
|
|||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
storagefactory "k8s.io/apiserver/pkg/storage/storagebackend/factory"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
type EtcdOptions struct {
|
||||
|
|
@ -176,6 +177,9 @@ func (s *EtcdOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
|
||||
fs.DurationVar(&s.StorageConfig.CountMetricPollPeriod, "etcd-count-metric-poll-period", s.StorageConfig.CountMetricPollPeriod, ""+
|
||||
"Frequency of polling etcd for number of resources per type. 0 disables the metric collection.")
|
||||
|
||||
fs.DurationVar(&s.StorageConfig.DBMetricPollInterval, "etcd-db-metric-poll-interval", s.StorageConfig.DBMetricPollInterval,
|
||||
"The interval of requests to poll etcd and update metric. 0 disables the metric collection")
|
||||
}
|
||||
|
||||
func (s *EtcdOptions) ApplyTo(c *server.Config) error {
|
||||
|
|
@ -235,12 +239,15 @@ func (f *SimpleRestOptionsFactory) GetRESTOptions(resource schema.GroupResource)
|
|||
if err != nil {
|
||||
return generic.RESTOptions{}, err
|
||||
}
|
||||
cacheSize, ok := sizes[resource]
|
||||
if !ok {
|
||||
cacheSize = f.Options.DefaultWatchCacheSize
|
||||
size, ok := sizes[resource]
|
||||
if ok && size > 0 {
|
||||
klog.Warningf("Dropping watch-cache-size for %v - watchCache size is now dynamic", resource)
|
||||
}
|
||||
if ok && size <= 0 {
|
||||
ret.Decorator = generic.UndecoratedStorage
|
||||
} else {
|
||||
ret.Decorator = genericregistry.StorageWithCacher()
|
||||
}
|
||||
// depending on cache size this might return an undecorated storage
|
||||
ret.Decorator = genericregistry.StorageWithCacher(cacheSize)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
|
@ -269,12 +276,15 @@ func (f *StorageFactoryRestOptionsFactory) GetRESTOptions(resource schema.GroupR
|
|||
if err != nil {
|
||||
return generic.RESTOptions{}, err
|
||||
}
|
||||
cacheSize, ok := sizes[resource]
|
||||
if !ok {
|
||||
cacheSize = f.Options.DefaultWatchCacheSize
|
||||
size, ok := sizes[resource]
|
||||
if ok && size > 0 {
|
||||
klog.Warningf("Dropping watch-cache-size for %v - watchCache size is now dynamic", resource)
|
||||
}
|
||||
if ok && size <= 0 {
|
||||
ret.Decorator = generic.UndecoratedStorage
|
||||
} else {
|
||||
ret.Decorator = genericregistry.StorageWithCacher()
|
||||
}
|
||||
// depending on cache size this might return an undecorated storage
|
||||
ret.Decorator = genericregistry.StorageWithCacher(cacheSize)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
|
|
|
|||
56
vendor/k8s.io/apiserver/pkg/server/options/events.go
generated
vendored
56
vendor/k8s.io/apiserver/pkg/server/options/events.go
generated
vendored
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
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"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ProcessInfo holds the apiserver process information used to send events
|
||||
type ProcessInfo struct {
|
||||
// Name of the api process to identify events
|
||||
Name string
|
||||
|
||||
// Namespace of the api process to send events
|
||||
Namespace string
|
||||
}
|
||||
|
||||
// NewProcessInfo returns a new process info with the hostname concatenated to the name given
|
||||
func NewProcessInfo(name, namespace string) *ProcessInfo {
|
||||
// try to concat the hostname if available
|
||||
host, _ := os.Hostname()
|
||||
if host != "" {
|
||||
name = fmt.Sprintf("%s-%s", name, host)
|
||||
}
|
||||
return &ProcessInfo{
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// validateProcessInfo checks for a complete process info
|
||||
func validateProcessInfo(p *ProcessInfo) error {
|
||||
if p == nil {
|
||||
return fmt.Errorf("ProcessInfo must be set")
|
||||
} else if p.Name == "" {
|
||||
return fmt.Errorf("ProcessInfo name must be set")
|
||||
} else if p.Namespace == "" {
|
||||
return fmt.Errorf("ProcessInfo namespace must be set")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
9
vendor/k8s.io/apiserver/pkg/server/options/recommended.go
generated
vendored
9
vendor/k8s.io/apiserver/pkg/server/options/recommended.go
generated
vendored
|
|
@ -48,14 +48,11 @@ type RecommendedOptions struct {
|
|||
// admission plugin initializers to Admission.ApplyTo.
|
||||
ExtraAdmissionInitializers func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error)
|
||||
Admission *AdmissionOptions
|
||||
// ProcessInfo is used to identify events created by the server.
|
||||
ProcessInfo *ProcessInfo
|
||||
Webhook *WebhookOptions
|
||||
// API Server Egress Selector is used to control outbound traffic from the API Server
|
||||
EgressSelector *EgressSelectorOptions
|
||||
}
|
||||
|
||||
func NewRecommendedOptions(prefix string, codec runtime.Codec, processInfo *ProcessInfo) *RecommendedOptions {
|
||||
func NewRecommendedOptions(prefix string, codec runtime.Codec) *RecommendedOptions {
|
||||
sso := NewSecureServingOptions()
|
||||
|
||||
// We are composing recommended options for an aggregated api-server,
|
||||
|
|
@ -78,8 +75,6 @@ func NewRecommendedOptions(prefix string, codec runtime.Codec, processInfo *Proc
|
|||
FeatureGate: feature.DefaultFeatureGate,
|
||||
ExtraAdmissionInitializers: func(c *server.RecommendedConfig) ([]admission.PluginInitializer, error) { return nil, nil },
|
||||
Admission: NewAdmissionOptions(),
|
||||
ProcessInfo: processInfo,
|
||||
Webhook: NewWebhookOptions(),
|
||||
EgressSelector: NewEgressSelectorOptions(),
|
||||
}
|
||||
}
|
||||
|
|
@ -111,7 +106,7 @@ func (o *RecommendedOptions) ApplyTo(config *server.RecommendedConfig) error {
|
|||
if err := o.Authorization.ApplyTo(&config.Config.Authorization); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Audit.ApplyTo(&config.Config, config.ClientConfig, config.SharedInformerFactory, o.ProcessInfo, o.Webhook); err != nil {
|
||||
if err := o.Audit.ApplyTo(&config.Config); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Features.ApplyTo(&config.Config); err != nil {
|
||||
|
|
|
|||
16
vendor/k8s.io/apiserver/pkg/server/options/server_run_options.go
generated
vendored
16
vendor/k8s.io/apiserver/pkg/server/options/server_run_options.go
generated
vendored
|
|
@ -50,7 +50,6 @@ type ServerRunOptions struct {
|
|||
// We intentionally did not add a flag for this option. Users of the
|
||||
// apiserver library can wire it to a flag.
|
||||
MaxRequestBodyBytes int64
|
||||
TargetRAMMB int
|
||||
EnablePriorityAndFairness bool
|
||||
}
|
||||
|
||||
|
|
@ -69,7 +68,7 @@ func NewServerRunOptions() *ServerRunOptions {
|
|||
}
|
||||
}
|
||||
|
||||
// ApplyOptions applies the run options to the method receiver and returns self
|
||||
// ApplyTo applies the run options to the method receiver and returns self
|
||||
func (s *ServerRunOptions) ApplyTo(c *server.Config) error {
|
||||
c.CorsAllowedOriginList = s.CorsAllowedOriginList
|
||||
c.ExternalAddress = s.ExternalHost
|
||||
|
|
@ -108,9 +107,6 @@ func (s *ServerRunOptions) DefaultAdvertiseAddress(secure *SecureServingOptions)
|
|||
// Validate checks validation of ServerRunOptions
|
||||
func (s *ServerRunOptions) Validate() []error {
|
||||
errors := []error{}
|
||||
if s.TargetRAMMB < 0 {
|
||||
errors = append(errors, fmt.Errorf("--target-ram-mb can not be negative value"))
|
||||
}
|
||||
|
||||
if s.LivezGracePeriod < 0 {
|
||||
errors = append(errors, fmt.Errorf("--livez-grace-period can not be a negative value"))
|
||||
|
|
@ -165,8 +161,10 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
|||
"List of allowed origins for CORS, comma separated. An allowed origin can be a regular "+
|
||||
"expression to support subdomain matching. If this list is empty CORS will not be enabled.")
|
||||
|
||||
fs.IntVar(&s.TargetRAMMB, "target-ram-mb", s.TargetRAMMB,
|
||||
"Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")
|
||||
deprecatedTargetRAMMB := 0
|
||||
fs.IntVar(&deprecatedTargetRAMMB, "target-ram-mb", deprecatedTargetRAMMB,
|
||||
"DEPRECATED: Memory limit for apiserver in MB (used to configure sizes of caches, etc.)")
|
||||
fs.MarkDeprecated("target-ram-mb", "This flag will be removed in v1.23")
|
||||
|
||||
fs.StringVar(&s.ExternalHost, "external-hostname", s.ExternalHost,
|
||||
"The hostname to use when generating externalized URLs for this master (e.g. Swagger API Docs or OpenID Discovery).")
|
||||
|
|
@ -209,8 +207,8 @@ func (s *ServerRunOptions) AddUniversalFlags(fs *pflag.FlagSet) {
|
|||
"If true and the APIPriorityAndFairness feature gate is enabled, replace the max-in-flight handler with an enhanced one that queues and dispatches with priority and fairness")
|
||||
|
||||
fs.DurationVar(&s.ShutdownDelayDuration, "shutdown-delay-duration", s.ShutdownDelayDuration, ""+
|
||||
"Time to delay the termination. During that time the server keeps serving requests normally and /healthz "+
|
||||
"returns success, but /readyz immediately returns failure. Graceful termination starts after this delay "+
|
||||
"Time to delay the termination. During that time the server keeps serving requests normally. The endpoints /healthz and /livez "+
|
||||
"will return success, but /readyz immediately returns failure. Graceful termination starts after this delay "+
|
||||
"has elapsed. This can be used to allow load balancer to stop sending traffic to this server.")
|
||||
|
||||
utilfeature.DefaultMutableFeatureGate.AddFlag(fs)
|
||||
|
|
|
|||
33
vendor/k8s.io/apiserver/pkg/server/options/serving.go
generated
vendored
33
vendor/k8s.io/apiserver/pkg/server/options/serving.go
generated
vendored
|
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||
package options
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"path"
|
||||
|
|
@ -24,7 +25,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
utilnet "k8s.io/apimachinery/pkg/util/net"
|
||||
"k8s.io/apiserver/pkg/server"
|
||||
|
|
@ -66,6 +67,10 @@ type SecureServingOptions struct {
|
|||
// HTTP2MaxStreamsPerConnection is the limit that the api server imposes on each client.
|
||||
// A value of zero means to use the default provided by golang's HTTP/2 support.
|
||||
HTTP2MaxStreamsPerConnection int
|
||||
|
||||
// PermitPortSharing controls if SO_REUSEPORT is used when binding the port, which allows
|
||||
// more than one instance to bind on the same address and port.
|
||||
PermitPortSharing bool
|
||||
}
|
||||
|
||||
type CertKey struct {
|
||||
|
|
@ -166,11 +171,13 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
fs.StringVar(&s.ServerCert.CertKey.KeyFile, "tls-private-key-file", s.ServerCert.CertKey.KeyFile,
|
||||
"File containing the default x509 private key matching --tls-cert-file.")
|
||||
|
||||
tlsCipherPossibleValues := cliflag.TLSCipherPossibleValues()
|
||||
tlsCipherPreferredValues := cliflag.PreferredTLSCipherNames()
|
||||
tlsCipherInsecureValues := cliflag.InsecureTLSCipherNames()
|
||||
fs.StringSliceVar(&s.CipherSuites, "tls-cipher-suites", s.CipherSuites,
|
||||
"Comma-separated list of cipher suites for the server. "+
|
||||
"If omitted, the default Go cipher suites will be use. "+
|
||||
"Possible values: "+strings.Join(tlsCipherPossibleValues, ","))
|
||||
"If omitted, the default Go cipher suites will be used. \n"+
|
||||
"Preferred values: "+strings.Join(tlsCipherPreferredValues, ", ")+". \n"+
|
||||
"Insecure values: "+strings.Join(tlsCipherInsecureValues, ", ")+".")
|
||||
|
||||
tlsPossibleVersions := cliflag.TLSPossibleVersions()
|
||||
fs.StringVar(&s.MinTLSVersion, "tls-min-version", s.MinTLSVersion,
|
||||
|
|
@ -192,6 +199,10 @@ func (s *SecureServingOptions) AddFlags(fs *pflag.FlagSet) {
|
|||
"The limit that the server gives to clients for "+
|
||||
"the maximum number of streams in an HTTP/2 connection. "+
|
||||
"Zero means to use golang's default.")
|
||||
|
||||
fs.BoolVar(&s.PermitPortSharing, "permit-port-sharing", s.PermitPortSharing,
|
||||
"If true, SO_REUSEPORT will be used when binding the port, which allows "+
|
||||
"more than one instance to bind on the same address and port. [default=false]")
|
||||
}
|
||||
|
||||
// ApplyTo fills up serving information in the server configuration.
|
||||
|
|
@ -206,7 +217,14 @@ func (s *SecureServingOptions) ApplyTo(config **server.SecureServingInfo) error
|
|||
if s.Listener == nil {
|
||||
var err error
|
||||
addr := net.JoinHostPort(s.BindAddress.String(), strconv.Itoa(s.BindPort))
|
||||
s.Listener, s.BindPort, err = CreateListener(s.BindNetwork, addr)
|
||||
|
||||
c := net.ListenConfig{}
|
||||
|
||||
if s.PermitPortSharing {
|
||||
c.Control = permitPortReuse
|
||||
}
|
||||
|
||||
s.Listener, s.BindPort, err = CreateListener(s.BindNetwork, addr, c)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create listener: %v", err)
|
||||
}
|
||||
|
|
@ -317,11 +335,12 @@ func (s *SecureServingOptions) MaybeDefaultWithSelfSignedCerts(publicAddress str
|
|||
return nil
|
||||
}
|
||||
|
||||
func CreateListener(network, addr string) (net.Listener, int, error) {
|
||||
func CreateListener(network, addr string, config net.ListenConfig) (net.Listener, int, error) {
|
||||
if len(network) == 0 {
|
||||
network = "tcp"
|
||||
}
|
||||
ln, err := net.Listen(network, addr)
|
||||
|
||||
ln, err := config.Listen(context.TODO(), network, addr)
|
||||
if err != nil {
|
||||
return nil, 0, fmt.Errorf("failed to listen on %v: %v", addr, err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
// +build !windows
|
||||
|
||||
/*
|
||||
Copyright 2018 The Kubernetes Authors.
|
||||
Copyright 2020 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.
|
||||
|
|
@ -17,18 +19,13 @@ limitations under the License.
|
|||
package options
|
||||
|
||||
import (
|
||||
utilwebhook "k8s.io/apiserver/pkg/util/webhook"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// WebhookOptions holds the outgoing webhook options
|
||||
type WebhookOptions struct {
|
||||
ServiceResolver utilwebhook.ServiceResolver
|
||||
AuthInfoResolverWrapper utilwebhook.AuthenticationInfoResolverWrapper
|
||||
}
|
||||
|
||||
// NewWebhookOptions returns the default options for outgoing webhooks
|
||||
func NewWebhookOptions() *WebhookOptions {
|
||||
return &WebhookOptions{
|
||||
ServiceResolver: utilwebhook.NewDefaultServiceResolver(),
|
||||
}
|
||||
func permitPortReuse(network, addr string, conn syscall.RawConn) error {
|
||||
return conn.Control(func(fd uintptr) {
|
||||
syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
||||
})
|
||||
}
|
||||
30
vendor/k8s.io/apiserver/pkg/server/options/serving_windows.go
generated
vendored
Normal file
30
vendor/k8s.io/apiserver/pkg/server/options/serving_windows.go
generated
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
// +build windows
|
||||
|
||||
/*
|
||||
Copyright 2020 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"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// Windows only supports SO_REUSEADDR, which may cause undefined behavior, as
|
||||
// there is no protection against port hijacking.
|
||||
func permitPortReuse(network, address string, c syscall.RawConn) error {
|
||||
return fmt.Errorf("port reuse is not supported on Windows")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue