Merge pull request #15516 from nikhiljindal/runtimeConfig
Enable extensions/v1beta1 by default and allow runtimeConfig to support enabling/disabling specific resources
This commit is contained in:
		@@ -9,6 +9,14 @@
 | 
			
		||||
    "path": "/api",
 | 
			
		||||
    "description": "get available API versions"
 | 
			
		||||
   },
 | 
			
		||||
   {
 | 
			
		||||
    "path": "/apis/extensions/v1beta1",
 | 
			
		||||
    "description": "API at /apis/extensions/v1beta1"
 | 
			
		||||
   },
 | 
			
		||||
   {
 | 
			
		||||
    "path": "/apis/extensions/",
 | 
			
		||||
    "description": "get information of a group"
 | 
			
		||||
   },
 | 
			
		||||
   {
 | 
			
		||||
    "path": "/apis",
 | 
			
		||||
    "description": "get available API versions"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3748
									
								
								api/swagger-spec/v1beta1.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3748
									
								
								api/swagger-spec/v1beta1.json
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -59,6 +59,14 @@ function verify-prereqs {
 | 
			
		||||
      fi
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
  if [[ "${ENABLE_DEPLOYMENTS}" == "true" ]]; then
 | 
			
		||||
    if [[ -z "${RUNTIME_CONFIG}" ]]; then
 | 
			
		||||
      RUNTIME_CONFIG="extensions/v1beta1/deployments=true"
 | 
			
		||||
    else
 | 
			
		||||
      RUNTIME_CONFIG="${RUNTIME_CONFIG},extensions/v1beta1/deployments=true"
 | 
			
		||||
    fi
 | 
			
		||||
  fi
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  local cmd
 | 
			
		||||
  for cmd in gcloud gsutil; do
 | 
			
		||||
 
 | 
			
		||||
@@ -408,30 +408,11 @@ func (s *APIServer) Run(_ []string) error {
 | 
			
		||||
		glog.Fatalf("Failure to start kubelet client: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// "api/all=false" allows users to selectively enable specific api versions.
 | 
			
		||||
	disableAllAPIs := false
 | 
			
		||||
	allAPIFlagValue, ok := s.RuntimeConfig["api/all"]
 | 
			
		||||
	if ok && allAPIFlagValue == "false" {
 | 
			
		||||
		disableAllAPIs = true
 | 
			
		||||
	apiGroupVersionOverrides, err := s.parseRuntimeConfig()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		glog.Fatalf("error in parsing runtime-config: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// "api/legacy=false" allows users to disable legacy api versions.
 | 
			
		||||
	disableLegacyAPIs := false
 | 
			
		||||
	legacyAPIFlagValue, ok := s.RuntimeConfig["api/legacy"]
 | 
			
		||||
	if ok && legacyAPIFlagValue == "false" {
 | 
			
		||||
		disableLegacyAPIs = true
 | 
			
		||||
	}
 | 
			
		||||
	_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
 | 
			
		||||
 | 
			
		||||
	// "api/v1={true|false} allows users to enable/disable v1 API.
 | 
			
		||||
	// This takes preference over api/all and api/legacy, if specified.
 | 
			
		||||
	disableV1 := disableAllAPIs
 | 
			
		||||
	disableV1 = !s.getRuntimeConfigValue("api/v1", !disableV1)
 | 
			
		||||
 | 
			
		||||
	// "extensions/v1beta1={true|false} allows users to enable/disable the experimental API.
 | 
			
		||||
	// This takes preference over api/all, if specified.
 | 
			
		||||
	enableExp := s.getRuntimeConfigValue("extensions/v1beta1", false)
 | 
			
		||||
 | 
			
		||||
	clientConfig := &client.Config{
 | 
			
		||||
		Host:    net.JoinHostPort(s.InsecureBindAddress.String(), strconv.Itoa(s.InsecurePort)),
 | 
			
		||||
		Version: s.DeprecatedStorageVersion,
 | 
			
		||||
@@ -458,17 +439,17 @@ func (s *APIServer) Run(_ []string) error {
 | 
			
		||||
	}
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
 | 
			
		||||
	if enableExp {
 | 
			
		||||
	if !apiGroupVersionOverrides["extensions/v1beta1"].Disable {
 | 
			
		||||
		expGroup, err := latest.Group("extensions")
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			glog.Fatalf("Experimental API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err)
 | 
			
		||||
			glog.Fatalf("Extensions API is enabled in runtime config, but not enabled in the environment variable KUBE_API_VERSIONS. Error: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if _, found := storageVersions[expGroup.Group]; !found {
 | 
			
		||||
			glog.Fatalf("Couldn't find the storage version for group: %q in storageVersions: %v", expGroup.Group, storageVersions)
 | 
			
		||||
		}
 | 
			
		||||
		expEtcdStorage, err := newEtcd(s.EtcdConfigFile, s.EtcdServerList, expGroup.InterfacesFor, storageVersions[expGroup.Group], s.EtcdPathPrefix)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			glog.Fatalf("Invalid experimental storage version or misconfigured etcd: %v", err)
 | 
			
		||||
			glog.Fatalf("Invalid extensions storage version or misconfigured etcd: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
	}
 | 
			
		||||
@@ -558,8 +539,7 @@ func (s *APIServer) Run(_ []string) error {
 | 
			
		||||
		SupportsBasicAuth:         len(s.BasicAuthFile) > 0,
 | 
			
		||||
		Authorizer:                authorizer,
 | 
			
		||||
		AdmissionControl:          admissionController,
 | 
			
		||||
		DisableV1:                 disableV1,
 | 
			
		||||
		EnableExp:                 enableExp,
 | 
			
		||||
		APIGroupVersionOverrides:  apiGroupVersionOverrides,
 | 
			
		||||
		MasterServiceNamespace:    s.MasterServiceNamespace,
 | 
			
		||||
		ClusterName:               s.ClusterName,
 | 
			
		||||
		ExternalHost:              s.ExternalHost,
 | 
			
		||||
@@ -680,3 +660,61 @@ func (s *APIServer) getRuntimeConfigValue(apiKey string, defaultValue bool) bool
 | 
			
		||||
	}
 | 
			
		||||
	return defaultValue
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Parses the given runtime-config and formats it into map[string]ApiGroupVersionOverride
 | 
			
		||||
func (s *APIServer) parseRuntimeConfig() (map[string]master.APIGroupVersionOverride, error) {
 | 
			
		||||
	// "api/all=false" allows users to selectively enable specific api versions.
 | 
			
		||||
	disableAllAPIs := false
 | 
			
		||||
	allAPIFlagValue, ok := s.RuntimeConfig["api/all"]
 | 
			
		||||
	if ok && allAPIFlagValue == "false" {
 | 
			
		||||
		disableAllAPIs = true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// "api/legacy=false" allows users to disable legacy api versions.
 | 
			
		||||
	disableLegacyAPIs := false
 | 
			
		||||
	legacyAPIFlagValue, ok := s.RuntimeConfig["api/legacy"]
 | 
			
		||||
	if ok && legacyAPIFlagValue == "false" {
 | 
			
		||||
		disableLegacyAPIs = true
 | 
			
		||||
	}
 | 
			
		||||
	_ = disableLegacyAPIs // hush the compiler while we don't have legacy APIs to disable.
 | 
			
		||||
 | 
			
		||||
	// "api/v1={true|false} allows users to enable/disable v1 API.
 | 
			
		||||
	// This takes preference over api/all and api/legacy, if specified.
 | 
			
		||||
	disableV1 := disableAllAPIs
 | 
			
		||||
	v1GroupVersion := "api/v1"
 | 
			
		||||
	disableV1 = !s.getRuntimeConfigValue(v1GroupVersion, !disableV1)
 | 
			
		||||
	apiGroupVersionOverrides := map[string]master.APIGroupVersionOverride{}
 | 
			
		||||
	if disableV1 {
 | 
			
		||||
		apiGroupVersionOverrides[v1GroupVersion] = master.APIGroupVersionOverride{
 | 
			
		||||
			Disable: true,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// "extensions/v1beta1={true|false} allows users to enable/disable the extensions API.
 | 
			
		||||
	// This takes preference over api/all, if specified.
 | 
			
		||||
	disableExtensions := disableAllAPIs
 | 
			
		||||
	extensionsGroupVersion := "extensions/v1beta1"
 | 
			
		||||
	// TODO: Make this a loop over all group/versions when there are more of them.
 | 
			
		||||
	disableExtensions = !s.getRuntimeConfigValue(extensionsGroupVersion, !disableExtensions)
 | 
			
		||||
	if disableExtensions {
 | 
			
		||||
		apiGroupVersionOverrides[extensionsGroupVersion] = master.APIGroupVersionOverride{
 | 
			
		||||
			Disable: true,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for key := range s.RuntimeConfig {
 | 
			
		||||
		if strings.HasPrefix(key, v1GroupVersion+"/") {
 | 
			
		||||
			return nil, fmt.Errorf("api/v1 resources cannot be enabled/disabled individually")
 | 
			
		||||
		} else if strings.HasPrefix(key, extensionsGroupVersion+"/") {
 | 
			
		||||
			resource := strings.TrimPrefix(key, extensionsGroupVersion+"/")
 | 
			
		||||
 | 
			
		||||
			apiGroupVersionOverride := apiGroupVersionOverrides[extensionsGroupVersion]
 | 
			
		||||
			if apiGroupVersionOverride.ResourceOverrides == nil {
 | 
			
		||||
				apiGroupVersionOverride.ResourceOverrides = map[string]bool{}
 | 
			
		||||
			}
 | 
			
		||||
			apiGroupVersionOverride.ResourceOverrides[resource] = s.getRuntimeConfigValue(key, false)
 | 
			
		||||
			apiGroupVersionOverrides[extensionsGroupVersion] = apiGroupVersionOverride
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return apiGroupVersionOverrides, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -154,3 +154,96 @@ func TestUpdateEtcdOverrides(t *testing.T) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestParseRuntimeConfig(t *testing.T) {
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		runtimeConfig            map[string]string
 | 
			
		||||
		apiGroupVersionOverrides map[string]master.APIGroupVersionOverride
 | 
			
		||||
		err                      bool
 | 
			
		||||
	}{
 | 
			
		||||
		{
 | 
			
		||||
			runtimeConfig:            map[string]string{},
 | 
			
		||||
			apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{},
 | 
			
		||||
			err: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// Cannot override v1 resources.
 | 
			
		||||
			runtimeConfig: map[string]string{
 | 
			
		||||
				"api/v1/pods": "false",
 | 
			
		||||
			},
 | 
			
		||||
			apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{},
 | 
			
		||||
			err: true,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// Disable v1.
 | 
			
		||||
			runtimeConfig: map[string]string{
 | 
			
		||||
				"api/v1": "false",
 | 
			
		||||
			},
 | 
			
		||||
			apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
 | 
			
		||||
				"api/v1": {
 | 
			
		||||
					Disable: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			err: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// Disable extensions.
 | 
			
		||||
			runtimeConfig: map[string]string{
 | 
			
		||||
				"extensions/v1beta1": "false",
 | 
			
		||||
			},
 | 
			
		||||
			apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
 | 
			
		||||
				"extensions/v1beta1": {
 | 
			
		||||
					Disable: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			err: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// Disable deployments.
 | 
			
		||||
			runtimeConfig: map[string]string{
 | 
			
		||||
				"extensions/v1beta1/deployments": "false",
 | 
			
		||||
			},
 | 
			
		||||
			apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
 | 
			
		||||
				"extensions/v1beta1": {
 | 
			
		||||
					ResourceOverrides: map[string]bool{
 | 
			
		||||
						"deployments": false,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			err: false,
 | 
			
		||||
		},
 | 
			
		||||
		{
 | 
			
		||||
			// Enable deployments and disable jobs.
 | 
			
		||||
			runtimeConfig: map[string]string{
 | 
			
		||||
				"extensions/v1beta1/deployments": "true",
 | 
			
		||||
				"extensions/v1beta1/jobs":        "false",
 | 
			
		||||
			},
 | 
			
		||||
			apiGroupVersionOverrides: map[string]master.APIGroupVersionOverride{
 | 
			
		||||
				"extensions/v1beta1": {
 | 
			
		||||
					ResourceOverrides: map[string]bool{
 | 
			
		||||
						"deployments": true,
 | 
			
		||||
						"jobs":        false,
 | 
			
		||||
					},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			err: false,
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	for _, test := range testCases {
 | 
			
		||||
		s := &APIServer{
 | 
			
		||||
			RuntimeConfig: test.runtimeConfig,
 | 
			
		||||
		}
 | 
			
		||||
		apiGroupVersionOverrides, err := s.parseRuntimeConfig()
 | 
			
		||||
 | 
			
		||||
		if err == nil && test.err {
 | 
			
		||||
			t.Fatalf("expected error for test: %q", test)
 | 
			
		||||
		} else if err != nil && !test.err {
 | 
			
		||||
			t.Fatalf("unexpected error: %s, for test: %q", err, test)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err == nil && !reflect.DeepEqual(apiGroupVersionOverrides, test.apiGroupVersionOverrides) {
 | 
			
		||||
			t.Fatalf("unexpected apiGroupVersionOverrides. Actual: %q, expected: %q", apiGroupVersionOverrides, test.apiGroupVersionOverrides)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -58,7 +58,6 @@ KUBE_API_VERSIONS="v1,extensions/v1beta1" "${KUBE_OUTPUT_HOSTBIN}/kube-apiserver
 | 
			
		||||
  --public-address-override="127.0.0.1" \
 | 
			
		||||
  --advertise-address="10.10.10.10" \
 | 
			
		||||
  --kubelet-port=${KUBELET_PORT} \
 | 
			
		||||
  --runtime-config=api/v1 \
 | 
			
		||||
  --service-cluster-ip-range="10.0.0.0/24" >/dev/null 2>&1 &
 | 
			
		||||
APISERVER_PID=$!
 | 
			
		||||
 | 
			
		||||
@@ -70,6 +69,7 @@ curl -fs ${SWAGGER_API_PATH} > ${SWAGGER_ROOT_DIR}/resourceListing.json
 | 
			
		||||
curl -fs ${SWAGGER_API_PATH}version > ${SWAGGER_ROOT_DIR}/version.json
 | 
			
		||||
curl -fs ${SWAGGER_API_PATH}api > ${SWAGGER_ROOT_DIR}/api.json
 | 
			
		||||
curl -fs ${SWAGGER_API_PATH}api/v1 > ${SWAGGER_ROOT_DIR}/v1.json
 | 
			
		||||
curl -fs ${SWAGGER_API_PATH}apis/extensions/v1beta1 > ${SWAGGER_ROOT_DIR}/v1beta1.json
 | 
			
		||||
 | 
			
		||||
kube::log::status "SUCCESS"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,7 @@ import (
 | 
			
		||||
	"k8s.io/kubernetes/pkg/ui"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/sets"
 | 
			
		||||
	utilSets "k8s.io/kubernetes/pkg/util/sets"
 | 
			
		||||
 | 
			
		||||
	daemonetcd "k8s.io/kubernetes/pkg/registry/daemonset/etcd"
 | 
			
		||||
	horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/horizontalpodautoscaler/etcd"
 | 
			
		||||
@@ -166,6 +167,15 @@ func (s *StorageDestinations) backends() []string {
 | 
			
		||||
	return backends.List()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Specifies the overrides for various API group versions.
 | 
			
		||||
// This can be used to enable/disable entire group versions or specific resources.
 | 
			
		||||
type APIGroupVersionOverride struct {
 | 
			
		||||
	// Whether to enable or disable this group version.
 | 
			
		||||
	Disable bool
 | 
			
		||||
	// List of overrides for individual resources in this group version.
 | 
			
		||||
	ResourceOverrides map[string]bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Config is a structure used to configure a Master.
 | 
			
		||||
type Config struct {
 | 
			
		||||
	StorageDestinations StorageDestinations
 | 
			
		||||
@@ -180,9 +190,8 @@ type Config struct {
 | 
			
		||||
	EnableUISupport       bool
 | 
			
		||||
	// allow downstream consumers to disable swagger
 | 
			
		||||
	EnableSwaggerSupport bool
 | 
			
		||||
	// allow api versions to be conditionally disabled
 | 
			
		||||
	DisableV1 bool
 | 
			
		||||
	EnableExp bool
 | 
			
		||||
	// Allows api group versions or specific resources to be conditionally enabled/disabled.
 | 
			
		||||
	APIGroupVersionOverrides map[string]APIGroupVersionOverride
 | 
			
		||||
	// allow downstream consumers to disable the index route
 | 
			
		||||
	EnableIndex           bool
 | 
			
		||||
	EnableProfiling       bool
 | 
			
		||||
@@ -271,26 +280,25 @@ type Master struct {
 | 
			
		||||
	cacheTimeout          time.Duration
 | 
			
		||||
	minRequestTimeout     time.Duration
 | 
			
		||||
 | 
			
		||||
	mux                   apiserver.Mux
 | 
			
		||||
	muxHelper             *apiserver.MuxHelper
 | 
			
		||||
	handlerContainer      *restful.Container
 | 
			
		||||
	rootWebService        *restful.WebService
 | 
			
		||||
	enableCoreControllers bool
 | 
			
		||||
	enableLogsSupport     bool
 | 
			
		||||
	enableUISupport       bool
 | 
			
		||||
	enableSwaggerSupport  bool
 | 
			
		||||
	enableProfiling       bool
 | 
			
		||||
	enableWatchCache      bool
 | 
			
		||||
	apiPrefix             string
 | 
			
		||||
	apiGroupPrefix        string
 | 
			
		||||
	corsAllowedOriginList []string
 | 
			
		||||
	authenticator         authenticator.Request
 | 
			
		||||
	authorizer            authorizer.Authorizer
 | 
			
		||||
	admissionControl      admission.Interface
 | 
			
		||||
	masterCount           int
 | 
			
		||||
	v1                    bool
 | 
			
		||||
	exp                   bool
 | 
			
		||||
	requestContextMapper  api.RequestContextMapper
 | 
			
		||||
	mux                      apiserver.Mux
 | 
			
		||||
	muxHelper                *apiserver.MuxHelper
 | 
			
		||||
	handlerContainer         *restful.Container
 | 
			
		||||
	rootWebService           *restful.WebService
 | 
			
		||||
	enableCoreControllers    bool
 | 
			
		||||
	enableLogsSupport        bool
 | 
			
		||||
	enableUISupport          bool
 | 
			
		||||
	enableSwaggerSupport     bool
 | 
			
		||||
	enableProfiling          bool
 | 
			
		||||
	enableWatchCache         bool
 | 
			
		||||
	apiPrefix                string
 | 
			
		||||
	apiGroupPrefix           string
 | 
			
		||||
	corsAllowedOriginList    []string
 | 
			
		||||
	authenticator            authenticator.Request
 | 
			
		||||
	authorizer               authorizer.Authorizer
 | 
			
		||||
	admissionControl         admission.Interface
 | 
			
		||||
	masterCount              int
 | 
			
		||||
	apiGroupVersionOverrides map[string]APIGroupVersionOverride
 | 
			
		||||
	requestContextMapper     api.RequestContextMapper
 | 
			
		||||
 | 
			
		||||
	// External host is the name that should be used in external (public internet) URLs for this master
 | 
			
		||||
	externalHost string
 | 
			
		||||
@@ -435,24 +443,23 @@ func New(c *Config) *Master {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m := &Master{
 | 
			
		||||
		serviceClusterIPRange: c.ServiceClusterIPRange,
 | 
			
		||||
		serviceNodePortRange:  c.ServiceNodePortRange,
 | 
			
		||||
		rootWebService:        new(restful.WebService),
 | 
			
		||||
		enableCoreControllers: c.EnableCoreControllers,
 | 
			
		||||
		enableLogsSupport:     c.EnableLogsSupport,
 | 
			
		||||
		enableUISupport:       c.EnableUISupport,
 | 
			
		||||
		enableSwaggerSupport:  c.EnableSwaggerSupport,
 | 
			
		||||
		enableProfiling:       c.EnableProfiling,
 | 
			
		||||
		enableWatchCache:      c.EnableWatchCache,
 | 
			
		||||
		apiPrefix:             c.APIPrefix,
 | 
			
		||||
		apiGroupPrefix:        c.APIGroupPrefix,
 | 
			
		||||
		corsAllowedOriginList: c.CorsAllowedOriginList,
 | 
			
		||||
		authenticator:         c.Authenticator,
 | 
			
		||||
		authorizer:            c.Authorizer,
 | 
			
		||||
		admissionControl:      c.AdmissionControl,
 | 
			
		||||
		v1:                    !c.DisableV1,
 | 
			
		||||
		exp:                   c.EnableExp,
 | 
			
		||||
		requestContextMapper:  c.RequestContextMapper,
 | 
			
		||||
		serviceClusterIPRange:    c.ServiceClusterIPRange,
 | 
			
		||||
		serviceNodePortRange:     c.ServiceNodePortRange,
 | 
			
		||||
		rootWebService:           new(restful.WebService),
 | 
			
		||||
		enableCoreControllers:    c.EnableCoreControllers,
 | 
			
		||||
		enableLogsSupport:        c.EnableLogsSupport,
 | 
			
		||||
		enableUISupport:          c.EnableUISupport,
 | 
			
		||||
		enableSwaggerSupport:     c.EnableSwaggerSupport,
 | 
			
		||||
		enableProfiling:          c.EnableProfiling,
 | 
			
		||||
		enableWatchCache:         c.EnableWatchCache,
 | 
			
		||||
		apiPrefix:                c.APIPrefix,
 | 
			
		||||
		apiGroupPrefix:           c.APIGroupPrefix,
 | 
			
		||||
		corsAllowedOriginList:    c.CorsAllowedOriginList,
 | 
			
		||||
		authenticator:            c.Authenticator,
 | 
			
		||||
		authorizer:               c.Authorizer,
 | 
			
		||||
		admissionControl:         c.AdmissionControl,
 | 
			
		||||
		apiGroupVersionOverrides: c.APIGroupVersionOverrides,
 | 
			
		||||
		requestContextMapper:     c.RequestContextMapper,
 | 
			
		||||
 | 
			
		||||
		cacheTimeout:      c.CacheTimeout,
 | 
			
		||||
		minRequestTimeout: time.Duration(c.MinRequestTimeout) * time.Second,
 | 
			
		||||
@@ -624,7 +631,8 @@ func (m *Master) init(c *Config) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	apiVersions := []string{}
 | 
			
		||||
	if m.v1 {
 | 
			
		||||
	// Install v1 unless disabled.
 | 
			
		||||
	if !m.apiGroupVersionOverrides["api/v1"].Disable {
 | 
			
		||||
		if err := m.api_v1().InstallREST(m.handlerContainer); err != nil {
 | 
			
		||||
			glog.Fatalf("Unable to setup API v1: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -637,7 +645,8 @@ func (m *Master) init(c *Config) {
 | 
			
		||||
 | 
			
		||||
	// allGroups records all supported groups at /apis
 | 
			
		||||
	allGroups := []unversioned.APIGroup{}
 | 
			
		||||
	if m.exp {
 | 
			
		||||
	// Install extensions unless disabled.
 | 
			
		||||
	if !m.apiGroupVersionOverrides["extensions/v1beta1"].Disable {
 | 
			
		||||
		m.thirdPartyStorage = c.StorageDestinations.APIGroups["extensions"].Default
 | 
			
		||||
		m.thirdPartyResources = map[string]*thirdpartyresourcedataetcd.REST{}
 | 
			
		||||
 | 
			
		||||
@@ -1023,45 +1032,71 @@ func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupV
 | 
			
		||||
 | 
			
		||||
// experimental returns the resources and codec for the experimental api
 | 
			
		||||
func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
 | 
			
		||||
	controllerStorage := expcontrolleretcd.NewStorage(c.StorageDestinations.get("", "replicationControllers"))
 | 
			
		||||
	// All resources except these are disabled by default.
 | 
			
		||||
	enabledResources := utilSets.NewString("jobs", "horizontalpodautoscalers", "ingress")
 | 
			
		||||
	resourceOverrides := m.apiGroupVersionOverrides["extensions/v1beta1"].ResourceOverrides
 | 
			
		||||
	isEnabled := func(resource string) bool {
 | 
			
		||||
		// Check if the resource has been overriden.
 | 
			
		||||
		enabled, ok := resourceOverrides[resource]
 | 
			
		||||
		if !ok {
 | 
			
		||||
			return enabledResources.Has(resource)
 | 
			
		||||
		}
 | 
			
		||||
		return enabled
 | 
			
		||||
	}
 | 
			
		||||
	dbClient := func(resource string) storage.Interface {
 | 
			
		||||
		return c.StorageDestinations.get("extensions", resource)
 | 
			
		||||
	}
 | 
			
		||||
	autoscalerStorage, autoscalerStatusStorage := horizontalpodautoscaleretcd.NewREST(dbClient("horizonalpodautoscalers"))
 | 
			
		||||
	thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(dbClient("thirdpartyresources"))
 | 
			
		||||
	daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(dbClient("daemonsets"))
 | 
			
		||||
	deploymentStorage := deploymentetcd.NewStorage(dbClient("deployments"))
 | 
			
		||||
	jobStorage, jobStatusStorage := jobetcd.NewREST(dbClient("jobs"))
 | 
			
		||||
	ingressStorage, ingressStatusStorage := ingressetcd.NewREST(dbClient("ingress"))
 | 
			
		||||
 | 
			
		||||
	thirdPartyControl := ThirdPartyController{
 | 
			
		||||
		master: m,
 | 
			
		||||
		thirdPartyResourceRegistry: thirdPartyResourceStorage,
 | 
			
		||||
	storage := map[string]rest.Storage{}
 | 
			
		||||
	if isEnabled("replicationcontrollers") {
 | 
			
		||||
		controllerStorage := expcontrolleretcd.NewStorage(c.StorageDestinations.get("", "replicationControllers"))
 | 
			
		||||
		storage["replicationcontrollers"] = controllerStorage.ReplicationController
 | 
			
		||||
		storage["replicationcontrollers/scale"] = controllerStorage.Scale
 | 
			
		||||
	}
 | 
			
		||||
	go func() {
 | 
			
		||||
		util.Forever(func() {
 | 
			
		||||
			if err := thirdPartyControl.SyncResources(); err != nil {
 | 
			
		||||
				glog.Warningf("third party resource sync failed: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
		}, 10*time.Second)
 | 
			
		||||
	}()
 | 
			
		||||
	storage := map[string]rest.Storage{
 | 
			
		||||
		strings.ToLower("replicationControllers"):          controllerStorage.ReplicationController,
 | 
			
		||||
		strings.ToLower("replicationControllers/scale"):    controllerStorage.Scale,
 | 
			
		||||
		strings.ToLower("horizontalpodautoscalers"):        autoscalerStorage,
 | 
			
		||||
		strings.ToLower("horizontalpodautoscalers/status"): autoscalerStatusStorage,
 | 
			
		||||
		strings.ToLower("thirdpartyresources"):             thirdPartyResourceStorage,
 | 
			
		||||
		strings.ToLower("daemonsets"):                      daemonSetStorage,
 | 
			
		||||
		strings.ToLower("daemonsets/status"):               daemonSetStatusStorage,
 | 
			
		||||
		strings.ToLower("deployments"):                     deploymentStorage.Deployment,
 | 
			
		||||
		strings.ToLower("deployments/scale"):               deploymentStorage.Scale,
 | 
			
		||||
		strings.ToLower("jobs"):                            jobStorage,
 | 
			
		||||
		strings.ToLower("jobs/status"):                     jobStatusStorage,
 | 
			
		||||
		strings.ToLower("ingress"):                         ingressStorage,
 | 
			
		||||
		strings.ToLower("ingress/status"):                  ingressStatusStorage,
 | 
			
		||||
	if isEnabled("horizontalpodautoscalers") {
 | 
			
		||||
		autoscalerStorage, autoscalerStatusStorage := horizontalpodautoscaleretcd.NewREST(dbClient("horizonalpodautoscalers"))
 | 
			
		||||
		storage["horizontalpodautoscalers"] = autoscalerStorage
 | 
			
		||||
		storage["horizontalpodautoscalers/status"] = autoscalerStatusStorage
 | 
			
		||||
	}
 | 
			
		||||
	if isEnabled("thirdpartyresources") {
 | 
			
		||||
		thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(dbClient("thirdpartyresources"))
 | 
			
		||||
		thirdPartyControl := ThirdPartyController{
 | 
			
		||||
			master: m,
 | 
			
		||||
			thirdPartyResourceRegistry: thirdPartyResourceStorage,
 | 
			
		||||
		}
 | 
			
		||||
		go func() {
 | 
			
		||||
			util.Forever(func() {
 | 
			
		||||
				if err := thirdPartyControl.SyncResources(); err != nil {
 | 
			
		||||
					glog.Warningf("third party resource sync failed: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
			}, 10*time.Second)
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		storage["thirdpartyresources"] = thirdPartyResourceStorage
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expMeta := latest.GroupOrDie("extensions")
 | 
			
		||||
	if isEnabled("daemonsets") {
 | 
			
		||||
		daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(dbClient("daemonsets"))
 | 
			
		||||
		storage["daemonsets"] = daemonSetStorage
 | 
			
		||||
		storage["daemonsets/status"] = daemonSetStatusStorage
 | 
			
		||||
	}
 | 
			
		||||
	if isEnabled("deployments") {
 | 
			
		||||
		deploymentStorage := deploymentetcd.NewStorage(dbClient("deployments"))
 | 
			
		||||
		storage["deployments"] = deploymentStorage.Deployment
 | 
			
		||||
		storage["deployments/scale"] = deploymentStorage.Scale
 | 
			
		||||
	}
 | 
			
		||||
	if isEnabled("jobs") {
 | 
			
		||||
		jobStorage, jobStatusStorage := jobetcd.NewREST(dbClient("jobs"))
 | 
			
		||||
		storage["jobs"] = jobStorage
 | 
			
		||||
		storage["jobs/status"] = jobStatusStorage
 | 
			
		||||
	}
 | 
			
		||||
	if isEnabled("ingress") {
 | 
			
		||||
		ingressStorage, ingressStatusStorage := ingressetcd.NewREST(dbClient("ingress"))
 | 
			
		||||
		storage["ingress"] = ingressStorage
 | 
			
		||||
		storage["ingress/status"] = ingressStatusStorage
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	extensionsGroup := latest.GroupOrDie("extensions")
 | 
			
		||||
 | 
			
		||||
	return &apiserver.APIGroupVersion{
 | 
			
		||||
		Root: m.apiGroupPrefix,
 | 
			
		||||
@@ -1071,11 +1106,11 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
 | 
			
		||||
		Convertor: api.Scheme,
 | 
			
		||||
		Typer:     api.Scheme,
 | 
			
		||||
 | 
			
		||||
		Mapper:        expMeta.RESTMapper,
 | 
			
		||||
		Codec:         expMeta.Codec,
 | 
			
		||||
		Linker:        expMeta.SelfLinker,
 | 
			
		||||
		Mapper:        extensionsGroup.RESTMapper,
 | 
			
		||||
		Codec:         extensionsGroup.Codec,
 | 
			
		||||
		Linker:        extensionsGroup.SelfLinker,
 | 
			
		||||
		Storage:       storage,
 | 
			
		||||
		Version:       expMeta.GroupVersion,
 | 
			
		||||
		Version:       extensionsGroup.GroupVersion,
 | 
			
		||||
		ServerVersion: latest.GroupOrDie("").GroupVersion,
 | 
			
		||||
 | 
			
		||||
		Admit:   m.admissionControl,
 | 
			
		||||
 
 | 
			
		||||
@@ -100,8 +100,7 @@ func TestNew(t *testing.T) {
 | 
			
		||||
	assert.Equal(master.authenticator, config.Authenticator)
 | 
			
		||||
	assert.Equal(master.authorizer, config.Authorizer)
 | 
			
		||||
	assert.Equal(master.admissionControl, config.AdmissionControl)
 | 
			
		||||
	assert.Equal(master.v1, !config.DisableV1)
 | 
			
		||||
	assert.Equal(master.exp, config.EnableExp)
 | 
			
		||||
	assert.Equal(master.apiGroupVersionOverrides, config.APIGroupVersionOverrides)
 | 
			
		||||
	assert.Equal(master.requestContextMapper, config.RequestContextMapper)
 | 
			
		||||
	assert.Equal(master.cacheTimeout, config.CacheTimeout)
 | 
			
		||||
	assert.Equal(master.masterCount, config.MasterCount)
 | 
			
		||||
@@ -366,7 +365,6 @@ func TestGetNodeAddresses(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
func TestDiscoveryAtAPIS(t *testing.T) {
 | 
			
		||||
	master, config, assert := setUp(t)
 | 
			
		||||
	master.exp = true
 | 
			
		||||
	// ================= preparation for master.init() ======================
 | 
			
		||||
	portRange := util.PortRange{Base: 10, Size: 10}
 | 
			
		||||
	master.serviceNodePortRange = portRange
 | 
			
		||||
 
 | 
			
		||||
@@ -390,8 +390,19 @@ func TestAuthModeAlwaysAllow(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
		m.Handler.ServeHTTP(w, req)
 | 
			
		||||
@@ -408,7 +419,7 @@ func TestAuthModeAlwaysAllow(t *testing.T) {
 | 
			
		||||
		APIPrefix:             "/api",
 | 
			
		||||
		Authorizer:            apiserver.NewAlwaysAllowAuthorizer(),
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	transport := http.DefaultTransport
 | 
			
		||||
@@ -508,8 +519,18 @@ func TestAuthModeAlwaysDeny(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
@@ -527,7 +548,7 @@ func TestAuthModeAlwaysDeny(t *testing.T) {
 | 
			
		||||
		APIPrefix:             "/api",
 | 
			
		||||
		Authorizer:            apiserver.NewAlwaysDenyAuthorizer(),
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	transport := http.DefaultTransport
 | 
			
		||||
@@ -578,8 +599,18 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
@@ -598,7 +629,7 @@ func TestAliceNotForbiddenOrUnauthorized(t *testing.T) {
 | 
			
		||||
		Authenticator:         getTestTokenAuth(),
 | 
			
		||||
		Authorizer:            allowAliceAuthorizer{},
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	previousResourceVersion := make(map[string]float64)
 | 
			
		||||
@@ -668,8 +699,18 @@ func TestBobIsForbidden(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
@@ -688,7 +729,7 @@ func TestBobIsForbidden(t *testing.T) {
 | 
			
		||||
		Authenticator:         getTestTokenAuth(),
 | 
			
		||||
		Authorizer:            allowAliceAuthorizer{},
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	transport := http.DefaultTransport
 | 
			
		||||
@@ -732,8 +773,18 @@ func TestUnknownUserIsUnauthorized(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
@@ -752,7 +803,7 @@ func TestUnknownUserIsUnauthorized(t *testing.T) {
 | 
			
		||||
		Authenticator:         getTestTokenAuth(),
 | 
			
		||||
		Authorizer:            allowAliceAuthorizer{},
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	transport := http.DefaultTransport
 | 
			
		||||
@@ -819,8 +870,18 @@ func TestAuthorizationAttributeDetermination(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	trackingAuthorizer := &trackingAuthorizer{}
 | 
			
		||||
 | 
			
		||||
@@ -841,7 +902,7 @@ func TestAuthorizationAttributeDetermination(t *testing.T) {
 | 
			
		||||
		Authenticator:         getTestTokenAuth(),
 | 
			
		||||
		Authorizer:            trackingAuthorizer,
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	transport := http.DefaultTransport
 | 
			
		||||
@@ -902,8 +963,18 @@ func TestNamespaceAuthorization(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	a := newAuthorizerWithContents(t, `{"namespace": "foo"}
 | 
			
		||||
`)
 | 
			
		||||
@@ -925,7 +996,7 @@ func TestNamespaceAuthorization(t *testing.T) {
 | 
			
		||||
		Authenticator:         getTestTokenAuth(),
 | 
			
		||||
		Authorizer:            a,
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	previousResourceVersion := make(map[string]float64)
 | 
			
		||||
@@ -1020,8 +1091,18 @@ func TestKindAuthorization(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	a := newAuthorizerWithContents(t, `{"resource": "services"}
 | 
			
		||||
`)
 | 
			
		||||
@@ -1043,7 +1124,7 @@ func TestKindAuthorization(t *testing.T) {
 | 
			
		||||
		Authenticator:         getTestTokenAuth(),
 | 
			
		||||
		Authorizer:            a,
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	previousResourceVersion := make(map[string]float64)
 | 
			
		||||
@@ -1126,8 +1207,18 @@ func TestReadOnlyAuthorization(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	a := newAuthorizerWithContents(t, `{"readonly": true}`)
 | 
			
		||||
 | 
			
		||||
@@ -1148,7 +1239,7 @@ func TestReadOnlyAuthorization(t *testing.T) {
 | 
			
		||||
		Authenticator:         getTestTokenAuth(),
 | 
			
		||||
		Authorizer:            a,
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	transport := http.DefaultTransport
 | 
			
		||||
 
 | 
			
		||||
@@ -44,6 +44,13 @@ func NewEtcdStorage() (storage.Interface, error) {
 | 
			
		||||
	return master.NewEtcdStorage(NewEtcdClient(), latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func NewExtensionsEtcdStorage(client *etcd.Client) (storage.Interface, error) {
 | 
			
		||||
	if client == nil {
 | 
			
		||||
		client = NewEtcdClient()
 | 
			
		||||
	}
 | 
			
		||||
	return master.NewEtcdStorage(client, latest.GroupOrDie("extensions").InterfacesFor, testapi.Extensions.GroupAndVersion(), etcdtest.PathPrefix())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func RequireEtcd() {
 | 
			
		||||
	if _, err := NewEtcdClient().Get("/", false, false); err != nil {
 | 
			
		||||
		glog.Fatalf("unable to connect to etcd for testing: %v", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -131,8 +131,8 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			glog.Fatalf("Failed to create etcd storage for master %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		expEtcdStorage, err := master.NewEtcdStorage(etcdClient, latest.GroupOrDie("extensions").InterfacesFor, latest.GroupOrDie("extensions").GroupVersion, etcdtest.PathPrefix())
 | 
			
		||||
		storageVersions["extensions"] = latest.GroupOrDie("extensions").GroupVersion
 | 
			
		||||
		expEtcdStorage, err := NewExtensionsEtcdStorage(etcdClient)
 | 
			
		||||
		storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			glog.Fatalf("Failed to create etcd storage for master %v", err)
 | 
			
		||||
		}
 | 
			
		||||
@@ -144,7 +144,6 @@ func startMasterOrDie(masterConfig *master.Config) (*master.Master, *httptest.Se
 | 
			
		||||
			StorageDestinations:  storageDestinations,
 | 
			
		||||
			StorageVersions:      storageVersions,
 | 
			
		||||
			KubeletClient:        client.FakeKubeletClient{},
 | 
			
		||||
			EnableExp:            true,
 | 
			
		||||
			EnableLogsSupport:    false,
 | 
			
		||||
			EnableProfiling:      true,
 | 
			
		||||
			EnableSwaggerSupport: true,
 | 
			
		||||
@@ -275,7 +274,7 @@ func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := master.NewEtcdStorage(etcdClient, latest.GroupOrDie("extensions").InterfacesFor, testapi.Extensions.GroupAndVersion(), etcdtest.PathPrefix())
 | 
			
		||||
	expEtcdStorage, err := NewExtensionsEtcdStorage(etcdClient)
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
@@ -292,7 +291,6 @@ func RunAMaster(t *testing.T) (*master.Master, *httptest.Server) {
 | 
			
		||||
		EnableUISupport:     false,
 | 
			
		||||
		APIPrefix:           "/api",
 | 
			
		||||
		APIGroupPrefix:      "/apis",
 | 
			
		||||
		EnableExp:           true,
 | 
			
		||||
		Authorizer:          apiserver.NewAlwaysAllowAuthorizer(),
 | 
			
		||||
		AdmissionControl:    admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:     storageVersions,
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@ func TestKubectlValidation(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
		// The following test the experimental api.
 | 
			
		||||
		// TOOD: Replace with something more robust. These may move.
 | 
			
		||||
		{`{"apiVersion": "extensions/v1beta1", "kind": "DaemonSet"}`, false},
 | 
			
		||||
		{`{"apiVersion": "extensions/v1beta1", "kind": "Ingress"}`, false},
 | 
			
		||||
		{`{"apiVersion": "extensions/v1beta1", "kind": "Job"}`, false},
 | 
			
		||||
		{`{"apiVersion": "vNotAVersion", "kind": "Job"}`, true},
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -59,8 +59,19 @@ func TestUnschedulableNodes(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("Couldn't create etcd storage: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	framework.DeleteAllEtcdKeys()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
@@ -79,7 +90,7 @@ func TestUnschedulableNodes(t *testing.T) {
 | 
			
		||||
		APIPrefix:             "/api",
 | 
			
		||||
		Authorizer:            apiserver.NewAlwaysAllowAuthorizer(),
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	restClient := client.NewOrDie(&client.Config{Host: s.URL, Version: testapi.Default.Version()})
 | 
			
		||||
@@ -298,8 +309,19 @@ func BenchmarkScheduling(b *testing.B) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatalf("Couldn't create etcd storage: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	framework.DeleteAllEtcdKeys()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
@@ -318,7 +340,7 @@ func BenchmarkScheduling(b *testing.B) {
 | 
			
		||||
		APIPrefix:             "/api",
 | 
			
		||||
		Authorizer:            apiserver.NewAlwaysAllowAuthorizer(),
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	c := client.NewOrDie(&client.Config{
 | 
			
		||||
 
 | 
			
		||||
@@ -51,8 +51,18 @@ func TestSecrets(t *testing.T) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
	s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
 | 
			
		||||
@@ -70,7 +80,7 @@ func TestSecrets(t *testing.T) {
 | 
			
		||||
		APIPrefix:             "/api",
 | 
			
		||||
		Authorizer:            apiserver.NewAlwaysAllowAuthorizer(),
 | 
			
		||||
		AdmissionControl:      admit.NewAlwaysAdmit(),
 | 
			
		||||
		StorageVersions:       map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:       storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	framework.DeleteAllEtcdKeys()
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,6 @@ import (
 | 
			
		||||
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/errors"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/latest"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/api/testapi"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/auth/authenticator"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/auth/authenticator/bearertoken"
 | 
			
		||||
@@ -44,11 +43,11 @@ import (
 | 
			
		||||
	"k8s.io/kubernetes/pkg/fields"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/labels"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/master"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/tools/etcdtest"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/sets"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/util/wait"
 | 
			
		||||
	serviceaccountadmission "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount"
 | 
			
		||||
	"k8s.io/kubernetes/plugin/pkg/auth/authenticator/request/union"
 | 
			
		||||
	"k8s.io/kubernetes/test/integration/framework"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
@@ -341,12 +340,23 @@ func startServiceAccountTestServer(t *testing.T) (*client.Client, client.Config,
 | 
			
		||||
	deleteAllEtcdKeys()
 | 
			
		||||
 | 
			
		||||
	// Etcd
 | 
			
		||||
	etcdStorage, err := master.NewEtcdStorage(newEtcdClient(), latest.GroupOrDie("").InterfacesFor, testapi.Default.Version(), etcdtest.PathPrefix())
 | 
			
		||||
	etcdStorage, err := framework.NewEtcdStorage()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	expEtcdStorage, err := framework.NewExtensionsEtcdStorage(nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatalf("unexpected error: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	storageDestinations := master.NewStorageDestinations()
 | 
			
		||||
	storageDestinations.AddAPIGroup("", etcdStorage)
 | 
			
		||||
	storageDestinations.AddAPIGroup("extensions", expEtcdStorage)
 | 
			
		||||
 | 
			
		||||
	storageVersions := make(map[string]string)
 | 
			
		||||
	storageVersions[""] = testapi.Default.Version()
 | 
			
		||||
	storageVersions["extensions"] = testapi.Extensions.GroupAndVersion()
 | 
			
		||||
 | 
			
		||||
	// Listener
 | 
			
		||||
	var m *master.Master
 | 
			
		||||
@@ -422,7 +432,7 @@ func startServiceAccountTestServer(t *testing.T) (*client.Client, client.Config,
 | 
			
		||||
		Authenticator:       authenticator,
 | 
			
		||||
		Authorizer:          authorizer,
 | 
			
		||||
		AdmissionControl:    serviceAccountAdmission,
 | 
			
		||||
		StorageVersions:     map[string]string{"": testapi.Default.Version()},
 | 
			
		||||
		StorageVersions:     storageVersions,
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	// Start the service account and service account token controllers
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user