...

Source file src/k8s.io/kube-aggregator/pkg/cmd/server/start.go

Documentation: k8s.io/kube-aggregator/pkg/cmd/server

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package server
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  
    24  	"github.com/spf13/cobra"
    25  	"github.com/spf13/pflag"
    26  	openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
    27  
    28  	utilerrors "k8s.io/apimachinery/pkg/util/errors"
    29  	"k8s.io/apimachinery/pkg/util/sets"
    30  	genericapiserver "k8s.io/apiserver/pkg/server"
    31  	"k8s.io/apiserver/pkg/server/filters"
    32  	genericoptions "k8s.io/apiserver/pkg/server/options"
    33  	"k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
    34  	"k8s.io/kube-aggregator/pkg/apiserver"
    35  	aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
    36  	"k8s.io/kube-aggregator/pkg/generated/openapi"
    37  )
    38  
    39  const defaultEtcdPathPrefix = "/registry/kube-aggregator.kubernetes.io/"
    40  
    41  // AggregatorOptions contains everything necessary to create and run an API Aggregator.
    42  type AggregatorOptions struct {
    43  	ServerRunOptions   *genericoptions.ServerRunOptions
    44  	RecommendedOptions *genericoptions.RecommendedOptions
    45  	APIEnablement      *genericoptions.APIEnablementOptions
    46  
    47  	// ProxyClientCert/Key are the client cert used to identify this proxy. Backing APIServices use
    48  	// this to confirm the proxy's identity
    49  	ProxyClientCertFile string
    50  	ProxyClientKeyFile  string
    51  
    52  	StdOut io.Writer
    53  	StdErr io.Writer
    54  }
    55  
    56  // NewCommandStartAggregator provides a CLI handler for 'start master' command
    57  // with a default AggregatorOptions.
    58  func NewCommandStartAggregator(defaults *AggregatorOptions, stopCh <-chan struct{}) *cobra.Command {
    59  	o := *defaults
    60  	cmd := &cobra.Command{
    61  		Short: "Launch a API aggregator and proxy server",
    62  		Long:  "Launch a API aggregator and proxy server",
    63  		RunE: func(c *cobra.Command, args []string) error {
    64  			if err := o.Complete(); err != nil {
    65  				return err
    66  			}
    67  			if err := o.Validate(args); err != nil {
    68  				return err
    69  			}
    70  			if err := o.RunAggregator(stopCh); err != nil {
    71  				return err
    72  			}
    73  			return nil
    74  		},
    75  	}
    76  
    77  	o.AddFlags(cmd.Flags())
    78  	return cmd
    79  }
    80  
    81  // AddFlags is necessary because hyperkube doesn't work using cobra, so we have to have different registration and execution paths
    82  func (o *AggregatorOptions) AddFlags(fs *pflag.FlagSet) {
    83  	o.ServerRunOptions.AddUniversalFlags(fs)
    84  	o.RecommendedOptions.AddFlags(fs)
    85  	o.APIEnablement.AddFlags(fs)
    86  	fs.StringVar(&o.ProxyClientCertFile, "proxy-client-cert-file", o.ProxyClientCertFile, "client certificate used identify the proxy to the API server")
    87  	fs.StringVar(&o.ProxyClientKeyFile, "proxy-client-key-file", o.ProxyClientKeyFile, "client certificate key used identify the proxy to the API server")
    88  }
    89  
    90  // NewDefaultOptions builds a "normal" set of options.  You wouldn't normally expose this, but hyperkube isn't cobra compatible
    91  func NewDefaultOptions(out, err io.Writer) *AggregatorOptions {
    92  	o := &AggregatorOptions{
    93  		ServerRunOptions: genericoptions.NewServerRunOptions(),
    94  		RecommendedOptions: genericoptions.NewRecommendedOptions(
    95  			defaultEtcdPathPrefix,
    96  			aggregatorscheme.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion),
    97  		),
    98  		APIEnablement: genericoptions.NewAPIEnablementOptions(),
    99  
   100  		StdOut: out,
   101  		StdErr: err,
   102  	}
   103  
   104  	return o
   105  }
   106  
   107  // Validate validates all the required options.
   108  func (o AggregatorOptions) Validate(args []string) error {
   109  	errors := []error{}
   110  	errors = append(errors, o.ServerRunOptions.Validate()...)
   111  	errors = append(errors, o.RecommendedOptions.Validate()...)
   112  	errors = append(errors, o.APIEnablement.Validate(aggregatorscheme.Scheme)...)
   113  	return utilerrors.NewAggregate(errors)
   114  }
   115  
   116  // Complete fills in missing Options.
   117  func (o *AggregatorOptions) Complete() error {
   118  	return nil
   119  }
   120  
   121  // RunAggregator runs the API Aggregator.
   122  func (o AggregatorOptions) RunAggregator(stopCh <-chan struct{}) error {
   123  	// TODO have a "real" external address
   124  	if err := o.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, nil); err != nil {
   125  		return fmt.Errorf("error creating self-signed certificates: %v", err)
   126  	}
   127  
   128  	serverConfig := genericapiserver.NewRecommendedConfig(aggregatorscheme.Codecs)
   129  
   130  	if err := o.ServerRunOptions.ApplyTo(&serverConfig.Config); err != nil {
   131  		return err
   132  	}
   133  	if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
   134  		return err
   135  	}
   136  	if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), aggregatorscheme.Scheme); err != nil {
   137  		return err
   138  	}
   139  	serverConfig.LongRunningFunc = filters.BasicLongRunningRequestCheck(
   140  		sets.NewString("watch", "proxy"),
   141  		sets.NewString("attach", "exec", "proxy", "log", "portforward"),
   142  	)
   143  	serverConfig.OpenAPIConfig = genericapiserver.DefaultOpenAPIConfig(openapi.GetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(aggregatorscheme.Scheme))
   144  	serverConfig.OpenAPIConfig.Info.Title = "kube-aggregator"
   145  	// prevent generic API server from installing the OpenAPI handler. Aggregator server
   146  	// has its own customized OpenAPI handler.
   147  	serverConfig.SkipOpenAPIInstallation = true
   148  
   149  	serviceResolver := apiserver.NewClusterIPServiceResolver(serverConfig.SharedInformerFactory.Core().V1().Services().Lister())
   150  
   151  	config := apiserver.Config{
   152  		GenericConfig: serverConfig,
   153  		ExtraConfig: apiserver.ExtraConfig{
   154  			ServiceResolver: serviceResolver,
   155  		},
   156  	}
   157  
   158  	if len(o.ProxyClientCertFile) == 0 || len(o.ProxyClientKeyFile) == 0 {
   159  		return errors.New("missing a client certificate along with a key to identify the proxy to the API server")
   160  	}
   161  
   162  	config.ExtraConfig.ProxyClientCertFile = o.ProxyClientCertFile
   163  	config.ExtraConfig.ProxyClientKeyFile = o.ProxyClientKeyFile
   164  
   165  	server, err := config.Complete().NewWithDelegate(genericapiserver.NewEmptyDelegate())
   166  	if err != nil {
   167  		return err
   168  	}
   169  
   170  	prepared, err := server.PrepareRun()
   171  	if err != nil {
   172  		return err
   173  	}
   174  	return prepared.Run(stopCh)
   175  }
   176  

View as plain text