2014-06-16 06:29:07 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2014 The Kubernetes Authors All rights reserved.
|
2014-06-16 06:29:07 +00:00
|
|
|
|
|
|
|
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 master
|
|
|
|
|
|
|
|
import (
|
2014-11-02 20:52:31 +00:00
|
|
|
"fmt"
|
2016-02-03 15:53:19 +00:00
|
|
|
"io"
|
2014-09-18 23:03:34 +00:00
|
|
|
"net"
|
2014-10-23 23:55:14 +00:00
|
|
|
"net/http"
|
2014-11-02 20:52:31 +00:00
|
|
|
"net/url"
|
2014-10-28 00:56:33 +00:00
|
|
|
"strconv"
|
2014-10-23 23:55:14 +00:00
|
|
|
"strings"
|
2015-06-04 18:58:38 +00:00
|
|
|
"sync"
|
2014-06-16 06:29:07 +00:00
|
|
|
"time"
|
|
|
|
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api"
|
2016-05-09 21:47:02 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api/meta"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api/rest"
|
2015-10-09 01:33:33 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
2016-03-22 16:45:23 +00:00
|
|
|
apiv1 "k8s.io/kubernetes/pkg/api/v1"
|
2016-01-13 22:40:56 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apimachinery/registered"
|
2016-04-15 22:30:15 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/apps"
|
|
|
|
appsapi "k8s.io/kubernetes/pkg/apis/apps/v1alpha1"
|
2016-02-15 14:00:40 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
2016-03-22 16:45:23 +00:00
|
|
|
autoscalingapiv1 "k8s.io/kubernetes/pkg/apis/autoscaling/v1"
|
2016-02-17 17:11:31 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/batch"
|
2016-03-22 16:45:23 +00:00
|
|
|
batchapiv1 "k8s.io/kubernetes/pkg/apis/batch/v1"
|
2016-04-25 12:47:50 +00:00
|
|
|
batchapiv2alpha1 "k8s.io/kubernetes/pkg/apis/batch/v2alpha1"
|
2016-04-14 01:45:43 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/certificates"
|
|
|
|
certificatesapiv1alpha1 "k8s.io/kubernetes/pkg/apis/certificates/v1alpha1"
|
2015-12-08 14:21:04 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
2016-03-22 16:45:23 +00:00
|
|
|
extensionsapiv1beta1 "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
|
2016-05-07 00:03:43 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/policy"
|
|
|
|
policyapiv1alpha1 "k8s.io/kubernetes/pkg/apis/policy/v1alpha1"
|
2016-05-25 21:20:41 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
|
|
rbacapi "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1"
|
|
|
|
rbacvalidation "k8s.io/kubernetes/pkg/apis/rbac/validation"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/apiserver"
|
2016-02-03 15:53:19 +00:00
|
|
|
apiservermetrics "k8s.io/kubernetes/pkg/apiserver/metrics"
|
2015-11-16 21:46:00 +00:00
|
|
|
"k8s.io/kubernetes/pkg/genericapiserver"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/healthz"
|
2015-10-27 13:18:45 +00:00
|
|
|
kubeletclient "k8s.io/kubernetes/pkg/kubelet/client"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/master/ports"
|
2016-04-14 01:45:43 +00:00
|
|
|
certificateetcd "k8s.io/kubernetes/pkg/registry/certificates/etcd"
|
2016-05-25 21:20:41 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/clusterrole"
|
|
|
|
clusterroleetcd "k8s.io/kubernetes/pkg/registry/clusterrole/etcd"
|
|
|
|
clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/clusterrole/policybased"
|
|
|
|
"k8s.io/kubernetes/pkg/registry/clusterrolebinding"
|
|
|
|
clusterrolebindingetcd "k8s.io/kubernetes/pkg/registry/clusterrolebinding/etcd"
|
|
|
|
clusterrolebindingpolicybased "k8s.io/kubernetes/pkg/registry/clusterrolebinding/policybased"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/componentstatus"
|
2015-12-15 15:09:42 +00:00
|
|
|
configmapetcd "k8s.io/kubernetes/pkg/registry/configmap/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
controlleretcd "k8s.io/kubernetes/pkg/registry/controller/etcd"
|
2015-08-29 05:19:32 +00:00
|
|
|
deploymentetcd "k8s.io/kubernetes/pkg/registry/deployment/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/endpoint"
|
|
|
|
endpointsetcd "k8s.io/kubernetes/pkg/registry/endpoint/etcd"
|
2015-08-11 09:21:00 +00:00
|
|
|
eventetcd "k8s.io/kubernetes/pkg/registry/event/etcd"
|
2015-08-06 16:53:34 +00:00
|
|
|
expcontrolleretcd "k8s.io/kubernetes/pkg/registry/experimental/controller/etcd"
|
2015-11-05 15:04:42 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/generic"
|
2015-09-22 18:26:36 +00:00
|
|
|
ingressetcd "k8s.io/kubernetes/pkg/registry/ingress/etcd"
|
2015-08-18 14:39:49 +00:00
|
|
|
jobetcd "k8s.io/kubernetes/pkg/registry/job/etcd"
|
2015-08-11 07:05:40 +00:00
|
|
|
limitrangeetcd "k8s.io/kubernetes/pkg/registry/limitrange/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/namespace"
|
|
|
|
namespaceetcd "k8s.io/kubernetes/pkg/registry/namespace/etcd"
|
2016-05-18 17:16:33 +00:00
|
|
|
networkpolicyetcd "k8s.io/kubernetes/pkg/registry/networkpolicy/etcd"
|
2015-09-09 14:18:17 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/node"
|
|
|
|
nodeetcd "k8s.io/kubernetes/pkg/registry/node/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
pvetcd "k8s.io/kubernetes/pkg/registry/persistentvolume/etcd"
|
|
|
|
pvcetcd "k8s.io/kubernetes/pkg/registry/persistentvolumeclaim/etcd"
|
2016-04-15 22:30:15 +00:00
|
|
|
petsetetcd "k8s.io/kubernetes/pkg/registry/petset/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
podetcd "k8s.io/kubernetes/pkg/registry/pod/etcd"
|
2016-05-07 00:03:43 +00:00
|
|
|
poddisruptionbudgetetcd "k8s.io/kubernetes/pkg/registry/poddisruptionbudget/etcd"
|
2015-12-14 13:31:23 +00:00
|
|
|
pspetcd "k8s.io/kubernetes/pkg/registry/podsecuritypolicy/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
podtemplateetcd "k8s.io/kubernetes/pkg/registry/podtemplate/etcd"
|
2016-01-19 00:06:57 +00:00
|
|
|
replicasetetcd "k8s.io/kubernetes/pkg/registry/replicaset/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
resourcequotaetcd "k8s.io/kubernetes/pkg/registry/resourcequota/etcd"
|
2016-05-25 21:20:41 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/role"
|
|
|
|
roleetcd "k8s.io/kubernetes/pkg/registry/role/etcd"
|
|
|
|
rolepolicybased "k8s.io/kubernetes/pkg/registry/role/policybased"
|
|
|
|
"k8s.io/kubernetes/pkg/registry/rolebinding"
|
|
|
|
rolebindingetcd "k8s.io/kubernetes/pkg/registry/rolebinding/etcd"
|
|
|
|
rolebindingpolicybased "k8s.io/kubernetes/pkg/registry/rolebinding/policybased"
|
2015-08-05 22:03:47 +00:00
|
|
|
secretetcd "k8s.io/kubernetes/pkg/registry/secret/etcd"
|
|
|
|
"k8s.io/kubernetes/pkg/registry/service"
|
|
|
|
etcdallocator "k8s.io/kubernetes/pkg/registry/service/allocator/etcd"
|
2015-08-06 10:02:01 +00:00
|
|
|
serviceetcd "k8s.io/kubernetes/pkg/registry/service/etcd"
|
2015-08-05 22:03:47 +00:00
|
|
|
ipallocator "k8s.io/kubernetes/pkg/registry/service/ipallocator"
|
|
|
|
serviceaccountetcd "k8s.io/kubernetes/pkg/registry/serviceaccount/etcd"
|
2015-08-15 05:10:15 +00:00
|
|
|
thirdpartyresourceetcd "k8s.io/kubernetes/pkg/registry/thirdpartyresource/etcd"
|
2015-08-20 05:08:26 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata"
|
2015-08-19 18:02:01 +00:00
|
|
|
thirdpartyresourcedataetcd "k8s.io/kubernetes/pkg/registry/thirdpartyresourcedata/etcd"
|
2015-12-21 05:27:49 +00:00
|
|
|
"k8s.io/kubernetes/pkg/runtime"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/storage"
|
2016-02-03 15:53:19 +00:00
|
|
|
etcdmetrics "k8s.io/kubernetes/pkg/storage/etcd/metrics"
|
2015-11-23 19:32:50 +00:00
|
|
|
etcdutil "k8s.io/kubernetes/pkg/storage/etcd/util"
|
2016-02-02 10:57:06 +00:00
|
|
|
"k8s.io/kubernetes/pkg/util/wait"
|
2014-10-23 23:55:14 +00:00
|
|
|
|
2015-09-08 23:58:25 +00:00
|
|
|
daemonetcd "k8s.io/kubernetes/pkg/registry/daemonset/etcd"
|
2015-08-06 14:14:28 +00:00
|
|
|
horizontalpodautoscaleretcd "k8s.io/kubernetes/pkg/registry/horizontalpodautoscaler/etcd"
|
|
|
|
|
2014-10-23 23:55:14 +00:00
|
|
|
"github.com/golang/glog"
|
2015-07-14 19:30:43 +00:00
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
2015-08-05 22:05:17 +00:00
|
|
|
"k8s.io/kubernetes/pkg/registry/service/allocator"
|
|
|
|
"k8s.io/kubernetes/pkg/registry/service/portallocator"
|
2014-06-16 06:29:07 +00:00
|
|
|
)
|
|
|
|
|
2016-06-24 15:25:46 +00:00
|
|
|
const (
|
|
|
|
// DefaultEndpointReconcilerInterval is the default amount of time for how often the endpoints for
|
|
|
|
// the kubernetes Service are reconciled.
|
|
|
|
DefaultEndpointReconcilerInterval = 10 * time.Second
|
|
|
|
)
|
|
|
|
|
2014-07-27 02:16:39 +00:00
|
|
|
type Config struct {
|
2015-11-16 21:46:00 +00:00
|
|
|
*genericapiserver.Config
|
2015-10-09 05:18:16 +00:00
|
|
|
|
2016-06-24 15:25:46 +00:00
|
|
|
EnableCoreControllers bool
|
|
|
|
EndpointReconcilerConfig EndpointReconcilerConfig
|
|
|
|
DeleteCollectionWorkers int
|
|
|
|
EventTTL time.Duration
|
|
|
|
KubeletClient kubeletclient.KubeletClient
|
2015-10-09 05:18:16 +00:00
|
|
|
// Used to start and monitor tunneling
|
2016-04-22 00:48:35 +00:00
|
|
|
Tunneler genericapiserver.Tunneler
|
2016-03-10 04:06:31 +00:00
|
|
|
|
|
|
|
disableThirdPartyControllerForTesting bool
|
2015-10-29 09:51:32 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 15:25:46 +00:00
|
|
|
// EndpointReconcilerConfig holds the endpoint reconciler and endpoint reconciliation interval to be
|
|
|
|
// used by the master.
|
|
|
|
type EndpointReconcilerConfig struct {
|
|
|
|
Reconciler EndpointReconciler
|
|
|
|
Interval time.Duration
|
|
|
|
}
|
|
|
|
|
2014-06-16 06:29:07 +00:00
|
|
|
// Master contains state for a Kubernetes cluster master/api server.
|
|
|
|
type Master struct {
|
2015-11-16 21:46:00 +00:00
|
|
|
*genericapiserver.GenericAPIServer
|
|
|
|
|
|
|
|
// Map of v1 resources to their REST storages.
|
|
|
|
v1ResourcesStorage map[string]rest.Storage
|
2015-02-12 00:07:54 +00:00
|
|
|
|
2016-02-18 13:50:43 +00:00
|
|
|
enableCoreControllers bool
|
|
|
|
deleteCollectionWorkers int
|
2015-02-12 00:07:54 +00:00
|
|
|
// registries are internal client APIs for accessing the storage layer
|
|
|
|
// TODO: define the internal typed interface in a way that clients can
|
|
|
|
// also be replaced
|
2015-09-09 14:18:17 +00:00
|
|
|
nodeRegistry node.Registry
|
2015-05-23 20:41:11 +00:00
|
|
|
namespaceRegistry namespace.Registry
|
|
|
|
serviceRegistry service.Registry
|
|
|
|
endpointRegistry endpoint.Registry
|
|
|
|
serviceClusterIPAllocator service.RangeRegistry
|
|
|
|
serviceNodePortAllocator service.RangeRegistry
|
2015-02-12 00:07:54 +00:00
|
|
|
|
2015-08-19 18:02:01 +00:00
|
|
|
// storage for third party objects
|
|
|
|
thirdPartyStorage storage.Interface
|
2015-12-10 00:35:35 +00:00
|
|
|
// map from api path to a tuple of (storage for the objects, APIGroup)
|
|
|
|
thirdPartyResources map[string]thirdPartyEntry
|
2015-09-09 21:36:19 +00:00
|
|
|
// protects the map
|
2015-11-16 21:46:00 +00:00
|
|
|
thirdPartyResourcesLock sync.RWMutex
|
2016-03-10 04:06:31 +00:00
|
|
|
// Useful for reliable testing. Shouldn't be used otherwise.
|
|
|
|
disableThirdPartyControllerForTesting bool
|
2014-06-16 06:29:07 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
// Used to start and monitor tunneling
|
2016-04-22 00:48:35 +00:00
|
|
|
tunneler genericapiserver.Tunneler
|
2014-10-28 00:56:33 +00:00
|
|
|
}
|
|
|
|
|
2015-12-10 00:35:35 +00:00
|
|
|
// thirdPartyEntry combines objects storage and API group into one struct
|
|
|
|
// for easy lookup.
|
|
|
|
type thirdPartyEntry struct {
|
|
|
|
storage *thirdpartyresourcedataetcd.REST
|
|
|
|
group unversioned.APIGroup
|
|
|
|
}
|
|
|
|
|
2014-10-28 20:02:19 +00:00
|
|
|
// New returns a new instance of Master from the given config.
|
2015-11-16 21:46:00 +00:00
|
|
|
// Certain config fields will be set to a default value if unset.
|
2014-10-28 20:02:19 +00:00
|
|
|
// Certain config fields must be specified, including:
|
|
|
|
// KubeletClient
|
2016-02-03 22:26:11 +00:00
|
|
|
func New(c *Config) (*Master, error) {
|
2014-11-03 22:50:41 +00:00
|
|
|
if c.KubeletClient == nil {
|
2016-02-03 22:26:11 +00:00
|
|
|
return nil, fmt.Errorf("Master.New() called with config.KubeletClient == nil")
|
2014-11-03 22:50:41 +00:00
|
|
|
}
|
2014-12-15 20:29:55 +00:00
|
|
|
|
2016-02-03 22:26:11 +00:00
|
|
|
s, err := genericapiserver.New(c.Config)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-11-16 21:46:00 +00:00
|
|
|
|
2014-06-16 06:29:07 +00:00
|
|
|
m := &Master{
|
2016-02-18 13:50:43 +00:00
|
|
|
GenericAPIServer: s,
|
|
|
|
enableCoreControllers: c.EnableCoreControllers,
|
|
|
|
deleteCollectionWorkers: c.DeleteCollectionWorkers,
|
|
|
|
tunneler: c.Tunneler,
|
2016-03-10 04:06:31 +00:00
|
|
|
|
|
|
|
disableThirdPartyControllerForTesting: c.disableThirdPartyControllerForTesting,
|
2014-06-16 06:29:07 +00:00
|
|
|
}
|
2015-11-16 21:46:00 +00:00
|
|
|
m.InstallAPIs(c)
|
2014-12-15 20:29:55 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
// TODO: Attempt clean shutdown?
|
|
|
|
if m.enableCoreControllers {
|
2016-06-24 15:25:46 +00:00
|
|
|
m.NewBootstrapController(c.EndpointReconcilerConfig).Start()
|
2015-11-16 21:46:00 +00:00
|
|
|
}
|
2015-05-06 21:54:54 +00:00
|
|
|
|
2016-02-03 22:26:11 +00:00
|
|
|
return m, nil
|
2014-06-16 06:29:07 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 21:52:28 +00:00
|
|
|
var defaultMetricsHandler = prometheus.Handler().ServeHTTP
|
|
|
|
|
|
|
|
// MetricsWithReset is a handler that resets metrics when DELETE is passed to the endpoint.
|
|
|
|
func MetricsWithReset(w http.ResponseWriter, req *http.Request) {
|
|
|
|
if req.Method == "DELETE" {
|
|
|
|
apiservermetrics.Reset()
|
|
|
|
etcdmetrics.Reset()
|
|
|
|
io.WriteString(w, "metrics reset\n")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defaultMetricsHandler(w, req)
|
2016-02-03 15:53:19 +00:00
|
|
|
}
|
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
func (m *Master) InstallAPIs(c *Config) {
|
2015-12-22 21:22:28 +00:00
|
|
|
apiGroupsInfo := []genericapiserver.APIGroupInfo{}
|
|
|
|
|
|
|
|
// Install v1 unless disabled.
|
2016-03-22 16:45:23 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(apiv1.SchemeGroupVersion) {
|
2015-12-22 21:22:28 +00:00
|
|
|
// Install v1 API.
|
|
|
|
m.initV1ResourcesStorage(c)
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
2016-01-13 22:40:56 +00:00
|
|
|
GroupMeta: *registered.GroupOrDie(api.GroupName),
|
2015-12-22 21:22:28 +00:00
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
|
|
|
"v1": m.v1ResourcesStorage,
|
|
|
|
},
|
2016-04-20 17:35:09 +00:00
|
|
|
IsLegacyGroup: true,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
2015-12-22 21:22:28 +00:00
|
|
|
}
|
2016-02-24 19:22:34 +00:00
|
|
|
if autoscalingGroupVersion := (unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}); registered.IsEnabledVersion(autoscalingGroupVersion) {
|
|
|
|
apiGroupInfo.SubresourceGroupVersionKind = map[string]unversioned.GroupVersionKind{
|
|
|
|
"replicationcontrollers/scale": autoscalingGroupVersion.WithKind("Scale"),
|
|
|
|
}
|
|
|
|
}
|
2015-12-22 21:22:28 +00:00
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
|
|
|
|
2015-12-05 02:01:29 +00:00
|
|
|
// Run the tunneler.
|
|
|
|
healthzChecks := []healthz.HealthzChecker{}
|
|
|
|
if m.tunneler != nil {
|
|
|
|
m.tunneler.Run(m.getNodeAddresses)
|
|
|
|
healthzChecks = append(healthzChecks, healthz.NamedCheck("SSH Tunnel Check", m.IsTunnelSyncHealthy))
|
|
|
|
prometheus.NewGaugeFunc(prometheus.GaugeOpts{
|
|
|
|
Name: "apiserver_proxy_tunnel_sync_latency_secs",
|
|
|
|
Help: "The time since the last successful synchronization of the SSH tunnels for proxy requests.",
|
|
|
|
}, func() float64 { return float64(m.tunneler.SecondsSinceSync()) })
|
|
|
|
}
|
2016-04-27 01:51:37 +00:00
|
|
|
healthz.InstallHandler(m.MuxHelper, healthzChecks...)
|
2016-04-06 21:52:28 +00:00
|
|
|
|
2016-02-03 15:53:19 +00:00
|
|
|
if c.EnableProfiling {
|
2016-04-06 21:52:28 +00:00
|
|
|
m.MuxHelper.HandleFunc("/metrics", MetricsWithReset)
|
|
|
|
} else {
|
|
|
|
m.MuxHelper.HandleFunc("/metrics", defaultMetricsHandler)
|
2016-02-03 15:53:19 +00:00
|
|
|
}
|
2015-12-05 02:01:29 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
// Install extensions unless disabled.
|
2016-03-22 16:45:23 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(extensionsapiv1beta1.SchemeGroupVersion) {
|
2016-03-16 14:17:04 +00:00
|
|
|
var err error
|
|
|
|
m.thirdPartyStorage, err = c.StorageFactory.New(extensions.Resource("thirdpartyresources"))
|
|
|
|
if err != nil {
|
|
|
|
glog.Fatalf("Error getting third party storage: %v", err)
|
|
|
|
}
|
2015-12-10 00:35:35 +00:00
|
|
|
m.thirdPartyResources = map[string]thirdPartyEntry{}
|
2015-11-16 21:46:00 +00:00
|
|
|
|
2015-12-22 21:22:28 +00:00
|
|
|
extensionResources := m.getExtensionResources(c)
|
2016-01-13 22:40:56 +00:00
|
|
|
extensionsGroupMeta := registered.GroupOrDie(extensions.GroupName)
|
2015-12-22 21:22:28 +00:00
|
|
|
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
|
|
|
GroupMeta: *extensionsGroupMeta,
|
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
|
|
|
"v1beta1": extensionResources,
|
2015-11-16 21:46:00 +00:00
|
|
|
},
|
2016-04-20 17:35:09 +00:00
|
|
|
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
2015-11-16 21:46:00 +00:00
|
|
|
}
|
2015-12-22 21:22:28 +00:00
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
2016-02-15 14:00:40 +00:00
|
|
|
|
|
|
|
// Install autoscaling unless disabled.
|
2016-03-22 16:45:23 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(autoscalingapiv1.SchemeGroupVersion) {
|
2016-02-15 14:00:40 +00:00
|
|
|
autoscalingResources := m.getAutoscalingResources(c)
|
|
|
|
autoscalingGroupMeta := registered.GroupOrDie(autoscaling.GroupName)
|
|
|
|
|
|
|
|
// Hard code preferred group version to autoscaling/v1
|
2016-03-22 16:45:23 +00:00
|
|
|
autoscalingGroupMeta.GroupVersion = autoscalingapiv1.SchemeGroupVersion
|
2016-02-15 14:00:40 +00:00
|
|
|
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
|
|
|
GroupMeta: *autoscalingGroupMeta,
|
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
|
|
|
"v1": autoscalingResources,
|
|
|
|
},
|
2016-04-20 17:35:09 +00:00
|
|
|
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
2016-02-15 14:00:40 +00:00
|
|
|
}
|
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
|
|
|
|
2016-02-17 17:11:31 +00:00
|
|
|
// Install batch unless disabled.
|
2016-04-25 12:47:50 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv1.SchemeGroupVersion) ||
|
|
|
|
c.APIResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) {
|
|
|
|
batchv1Resources := m.getBatchResources(c, batchapiv1.SchemeGroupVersion)
|
2016-02-17 17:11:31 +00:00
|
|
|
batchGroupMeta := registered.GroupOrDie(batch.GroupName)
|
|
|
|
|
|
|
|
// Hard code preferred group version to batch/v1
|
2016-03-22 16:45:23 +00:00
|
|
|
batchGroupMeta.GroupVersion = batchapiv1.SchemeGroupVersion
|
2016-02-17 17:11:31 +00:00
|
|
|
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
|
|
|
GroupMeta: *batchGroupMeta,
|
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
2016-04-25 12:47:50 +00:00
|
|
|
"v1": batchv1Resources,
|
2016-02-17 17:11:31 +00:00
|
|
|
},
|
2016-04-20 17:35:09 +00:00
|
|
|
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
2016-02-17 17:11:31 +00:00
|
|
|
}
|
2016-04-25 12:47:50 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(batchapiv2alpha1.SchemeGroupVersion) {
|
|
|
|
batchv2alpha1Resources := m.getBatchResources(c, batchapiv2alpha1.SchemeGroupVersion)
|
|
|
|
apiGroupInfo.VersionedResourcesStorageMap["v2alpha1"] = batchv2alpha1Resources
|
|
|
|
}
|
2016-02-17 17:11:31 +00:00
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
|
|
|
|
2016-05-07 00:03:43 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(policyapiv1alpha1.SchemeGroupVersion) {
|
|
|
|
policyResources := m.getPolicyResources(c)
|
|
|
|
policyGroupMeta := registered.GroupOrDie(policy.GroupName)
|
|
|
|
|
|
|
|
// Hard code preferred group version to policy/v1alpha1
|
|
|
|
policyGroupMeta.GroupVersion = policyapiv1alpha1.SchemeGroupVersion
|
|
|
|
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
|
|
|
GroupMeta: *policyGroupMeta,
|
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
|
|
|
"v1alpha1": policyResources,
|
|
|
|
},
|
|
|
|
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
|
|
|
}
|
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
|
|
|
|
2016-04-15 22:30:15 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(appsapi.SchemeGroupVersion) {
|
|
|
|
appsResources := m.getAppsResources(c)
|
|
|
|
appsGroupMeta := registered.GroupOrDie(apps.GroupName)
|
|
|
|
|
|
|
|
// Hard code preferred group version to apps/v1alpha1
|
|
|
|
appsGroupMeta.GroupVersion = appsapi.SchemeGroupVersion
|
|
|
|
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
|
|
|
GroupMeta: *appsGroupMeta,
|
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
|
|
|
"v1alpha1": appsResources,
|
|
|
|
},
|
2016-04-20 17:35:09 +00:00
|
|
|
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
2016-04-15 22:30:15 +00:00
|
|
|
}
|
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
2016-05-25 21:20:41 +00:00
|
|
|
|
2016-04-14 01:45:43 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(certificatesapiv1alpha1.SchemeGroupVersion) {
|
|
|
|
certificateResources := m.getCertificateResources(c)
|
|
|
|
certificatesGroupMeta := registered.GroupOrDie(certificates.GroupName)
|
|
|
|
|
|
|
|
// Hard code preferred group version to certificates/v1alpha1
|
|
|
|
certificatesGroupMeta.GroupVersion = certificatesapiv1alpha1.SchemeGroupVersion
|
|
|
|
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
|
|
|
GroupMeta: *certificatesGroupMeta,
|
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
|
|
|
"v1alpha1": certificateResources,
|
|
|
|
},
|
|
|
|
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
|
|
|
}
|
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
|
|
|
|
2016-05-25 21:20:41 +00:00
|
|
|
if c.APIResourceConfigSource.AnyResourcesForVersionEnabled(rbacapi.SchemeGroupVersion) {
|
|
|
|
rbacResources := m.getRBACResources(c)
|
|
|
|
rbacGroupMeta := registered.GroupOrDie(rbac.GroupName)
|
|
|
|
|
|
|
|
// Hard code preferred group version to rbac/v1alpha1
|
|
|
|
rbacGroupMeta.GroupVersion = rbacapi.SchemeGroupVersion
|
|
|
|
|
|
|
|
apiGroupInfo := genericapiserver.APIGroupInfo{
|
|
|
|
GroupMeta: *rbacGroupMeta,
|
|
|
|
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{
|
|
|
|
"v1alpha1": rbacResources,
|
|
|
|
},
|
|
|
|
OptionsExternalVersion: ®istered.GroupOrDie(api.GroupName).GroupVersion,
|
|
|
|
Scheme: api.Scheme,
|
|
|
|
ParameterCodec: api.ParameterCodec,
|
|
|
|
NegotiatedSerializer: api.Codecs,
|
|
|
|
}
|
|
|
|
apiGroupsInfo = append(apiGroupsInfo, apiGroupInfo)
|
|
|
|
}
|
|
|
|
|
2015-12-22 21:22:28 +00:00
|
|
|
if err := m.InstallAPIGroups(apiGroupsInfo); err != nil {
|
|
|
|
glog.Fatalf("Error in registering group versions: %v", err)
|
2015-10-09 05:18:16 +00:00
|
|
|
}
|
2015-11-16 21:46:00 +00:00
|
|
|
}
|
2015-10-09 05:18:16 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
func (m *Master) initV1ResourcesStorage(c *Config) {
|
2016-02-22 09:15:22 +00:00
|
|
|
restOptions := func(resource string) generic.RESTOptions {
|
2016-03-16 14:17:04 +00:00
|
|
|
return m.GetRESTOptionsOrDie(c, api.Resource(resource))
|
2016-02-22 09:15:22 +00:00
|
|
|
}
|
2015-02-11 23:37:12 +00:00
|
|
|
|
2016-02-22 09:15:22 +00:00
|
|
|
podTemplateStorage := podtemplateetcd.NewREST(restOptions("podTemplates"))
|
2015-03-04 00:54:17 +00:00
|
|
|
|
2016-02-22 09:15:22 +00:00
|
|
|
eventStorage := eventetcd.NewREST(restOptions("events"), uint64(c.EventTTL.Seconds()))
|
|
|
|
limitRangeStorage := limitrangeetcd.NewREST(restOptions("limitRanges"))
|
2015-03-13 19:15:04 +00:00
|
|
|
|
2016-02-22 09:15:22 +00:00
|
|
|
resourceQuotaStorage, resourceQuotaStatusStorage := resourcequotaetcd.NewREST(restOptions("resourceQuotas"))
|
|
|
|
secretStorage := secretetcd.NewREST(restOptions("secrets"))
|
|
|
|
serviceAccountStorage := serviceaccountetcd.NewREST(restOptions("serviceAccounts"))
|
|
|
|
persistentVolumeStorage, persistentVolumeStatusStorage := pvetcd.NewREST(restOptions("persistentVolumes"))
|
|
|
|
persistentVolumeClaimStorage, persistentVolumeClaimStatusStorage := pvcetcd.NewREST(restOptions("persistentVolumeClaims"))
|
|
|
|
configMapStorage := configmapetcd.NewREST(restOptions("configMaps"))
|
2015-03-12 15:08:06 +00:00
|
|
|
|
2016-02-22 09:15:22 +00:00
|
|
|
namespaceStorage, namespaceStatusStorage, namespaceFinalizeStorage := namespaceetcd.NewREST(restOptions("namespaces"))
|
2015-03-12 15:08:06 +00:00
|
|
|
m.namespaceRegistry = namespace.NewRegistry(namespaceStorage)
|
2015-02-12 00:07:54 +00:00
|
|
|
|
2016-02-22 09:15:22 +00:00
|
|
|
endpointsStorage := endpointsetcd.NewREST(restOptions("endpoints"))
|
2015-03-15 06:03:46 +00:00
|
|
|
m.endpointRegistry = endpoint.NewRegistry(endpointsStorage)
|
|
|
|
|
2016-02-22 09:15:22 +00:00
|
|
|
nodeStorage := nodeetcd.NewStorage(restOptions("nodes"), c.KubeletClient, m.ProxyTransport)
|
2015-11-30 11:48:23 +00:00
|
|
|
m.nodeRegistry = node.NewRegistry(nodeStorage.Node)
|
2015-03-13 14:49:38 +00:00
|
|
|
|
2015-10-27 13:18:45 +00:00
|
|
|
podStorage := podetcd.NewStorage(
|
2016-02-22 09:15:22 +00:00
|
|
|
restOptions("pods"),
|
2015-11-30 11:48:23 +00:00
|
|
|
kubeletclient.ConnectionInfoGetter(nodeStorage.Node),
|
2015-11-16 21:46:00 +00:00
|
|
|
m.ProxyTransport,
|
2015-10-27 13:18:45 +00:00
|
|
|
)
|
|
|
|
|
2016-03-16 14:17:04 +00:00
|
|
|
serviceRESTStorage, serviceStatusStorage := serviceetcd.NewREST(restOptions("services"))
|
|
|
|
m.serviceRegistry = service.NewRegistry(serviceRESTStorage)
|
2015-02-11 23:37:12 +00:00
|
|
|
|
2015-05-23 20:41:11 +00:00
|
|
|
var serviceClusterIPRegistry service.RangeRegistry
|
2015-11-16 21:46:00 +00:00
|
|
|
serviceClusterIPRange := m.ServiceClusterIPRange
|
|
|
|
if serviceClusterIPRange == nil {
|
|
|
|
glog.Fatalf("service clusterIPRange is nil")
|
|
|
|
return
|
|
|
|
}
|
2016-03-16 14:17:04 +00:00
|
|
|
|
|
|
|
serviceStorage, err := c.StorageFactory.New(api.Resource("services"))
|
|
|
|
if err != nil {
|
|
|
|
glog.Fatal(err.Error())
|
|
|
|
}
|
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
serviceClusterIPAllocator := ipallocator.NewAllocatorCIDRRange(serviceClusterIPRange, func(max int, rangeSpec string) allocator.Interface {
|
2015-05-22 22:28:48 +00:00
|
|
|
mem := allocator.NewAllocationMap(max, rangeSpec)
|
2016-03-16 14:17:04 +00:00
|
|
|
// TODO etcdallocator package to return a storage interface via the storageFactory
|
|
|
|
etcd := etcdallocator.NewEtcd(mem, "/ranges/serviceips", api.Resource("serviceipallocations"), serviceStorage)
|
2015-05-23 20:41:11 +00:00
|
|
|
serviceClusterIPRegistry = etcd
|
2015-05-22 22:28:48 +00:00
|
|
|
return etcd
|
|
|
|
})
|
2015-05-23 20:41:11 +00:00
|
|
|
m.serviceClusterIPAllocator = serviceClusterIPRegistry
|
2015-05-22 22:28:48 +00:00
|
|
|
|
|
|
|
var serviceNodePortRegistry service.RangeRegistry
|
2015-11-16 21:46:00 +00:00
|
|
|
serviceNodePortAllocator := portallocator.NewPortAllocatorCustom(m.ServiceNodePortRange, func(max int, rangeSpec string) allocator.Interface {
|
2015-05-22 22:28:48 +00:00
|
|
|
mem := allocator.NewAllocationMap(max, rangeSpec)
|
2016-03-16 14:17:04 +00:00
|
|
|
// TODO etcdallocator package to return a storage interface via the storageFactory
|
|
|
|
etcd := etcdallocator.NewEtcd(mem, "/ranges/servicenodeports", api.Resource("servicenodeportallocations"), serviceStorage)
|
2015-05-22 22:28:48 +00:00
|
|
|
serviceNodePortRegistry = etcd
|
|
|
|
return etcd
|
|
|
|
})
|
|
|
|
m.serviceNodePortAllocator = serviceNodePortRegistry
|
2015-05-03 22:44:05 +00:00
|
|
|
|
2016-02-24 19:22:34 +00:00
|
|
|
controllerStorage := controlleretcd.NewStorage(restOptions("replicationControllers"))
|
2015-03-16 04:36:26 +00:00
|
|
|
|
2015-11-18 03:42:03 +00:00
|
|
|
serviceRest := service.NewStorage(m.serviceRegistry, m.endpointRegistry, serviceClusterIPAllocator, serviceNodePortAllocator, m.ProxyTransport)
|
|
|
|
|
|
|
|
// TODO: Factor out the core API registration
|
2015-11-16 21:46:00 +00:00
|
|
|
m.v1ResourcesStorage = map[string]rest.Storage{
|
2015-04-14 15:12:27 +00:00
|
|
|
"pods": podStorage.Pod,
|
2015-07-28 22:56:27 +00:00
|
|
|
"pods/attach": podStorage.Attach,
|
2015-04-14 15:12:27 +00:00
|
|
|
"pods/status": podStorage.Status,
|
|
|
|
"pods/log": podStorage.Log,
|
|
|
|
"pods/exec": podStorage.Exec,
|
|
|
|
"pods/portforward": podStorage.PortForward,
|
|
|
|
"pods/proxy": podStorage.Proxy,
|
|
|
|
"pods/binding": podStorage.Binding,
|
|
|
|
"bindings": podStorage.Binding,
|
2015-02-11 23:37:12 +00:00
|
|
|
|
2015-03-04 00:54:17 +00:00
|
|
|
"podTemplates": podTemplateStorage,
|
|
|
|
|
2016-02-24 19:22:34 +00:00
|
|
|
"replicationControllers": controllerStorage.Controller,
|
|
|
|
"replicationControllers/status": controllerStorage.Status,
|
2015-11-18 03:42:03 +00:00
|
|
|
|
|
|
|
"services": serviceRest.Service,
|
|
|
|
"services/proxy": serviceRest.Proxy,
|
|
|
|
"services/status": serviceStatusStorage,
|
|
|
|
|
|
|
|
"endpoints": endpointsStorage,
|
|
|
|
|
|
|
|
"nodes": nodeStorage.Node,
|
|
|
|
"nodes/status": nodeStorage.Status,
|
|
|
|
"nodes/proxy": nodeStorage.Proxy,
|
|
|
|
|
|
|
|
"events": eventStorage,
|
2014-08-15 23:01:33 +00:00
|
|
|
|
2015-08-11 07:05:40 +00:00
|
|
|
"limitRanges": limitRangeStorage,
|
2015-04-06 18:40:45 +00:00
|
|
|
"resourceQuotas": resourceQuotaStorage,
|
|
|
|
"resourceQuotas/status": resourceQuotaStatusStorage,
|
|
|
|
"namespaces": namespaceStorage,
|
|
|
|
"namespaces/status": namespaceStatusStorage,
|
|
|
|
"namespaces/finalize": namespaceFinalizeStorage,
|
2015-04-28 03:50:56 +00:00
|
|
|
"secrets": secretStorage,
|
2015-04-27 22:53:28 +00:00
|
|
|
"serviceAccounts": serviceAccountStorage,
|
2015-04-06 18:40:45 +00:00
|
|
|
"persistentVolumes": persistentVolumeStorage,
|
|
|
|
"persistentVolumes/status": persistentVolumeStatusStorage,
|
|
|
|
"persistentVolumeClaims": persistentVolumeClaimStorage,
|
|
|
|
"persistentVolumeClaims/status": persistentVolumeClaimStatusStorage,
|
2016-01-15 16:48:36 +00:00
|
|
|
"configMaps": configMapStorage,
|
2015-04-15 19:23:02 +00:00
|
|
|
|
2015-05-14 00:29:25 +00:00
|
|
|
"componentStatuses": componentstatus.NewStorage(func() map[string]apiserver.Server { return m.getServersToValidate(c) }),
|
2014-06-16 06:29:07 +00:00
|
|
|
}
|
2016-02-24 19:22:34 +00:00
|
|
|
if registered.IsEnabledVersion(unversioned.GroupVersion{Group: "autoscaling", Version: "v1"}) {
|
|
|
|
m.v1ResourcesStorage["replicationControllers/scale"] = controllerStorage.Scale
|
|
|
|
}
|
2015-05-04 19:11:19 +00:00
|
|
|
}
|
|
|
|
|
2016-06-24 15:25:46 +00:00
|
|
|
// NewBootstrapController returns a controller for watching the core capabilities of the master. If
|
|
|
|
// endpointReconcilerConfig.Interval is 0, the default value of DefaultEndpointReconcilerInterval
|
|
|
|
// will be used instead. If endpointReconcilerConfig.Reconciler is nil, the default
|
|
|
|
// MasterCountEndpointReconciler will be used.
|
|
|
|
func (m *Master) NewBootstrapController(endpointReconcilerConfig EndpointReconcilerConfig) *Controller {
|
|
|
|
if endpointReconcilerConfig.Interval == 0 {
|
|
|
|
endpointReconcilerConfig.Interval = DefaultEndpointReconcilerInterval
|
|
|
|
}
|
|
|
|
|
|
|
|
if endpointReconcilerConfig.Reconciler == nil {
|
|
|
|
// use a default endpoint reconciler if nothing is set
|
|
|
|
// m.endpointRegistry is set via m.InstallAPIs -> m.initV1ResourcesStorage
|
|
|
|
endpointReconcilerConfig.Reconciler = NewMasterCountEndpointReconciler(m.MasterCount, m.endpointRegistry)
|
|
|
|
}
|
|
|
|
|
2015-05-04 19:11:19 +00:00
|
|
|
return &Controller{
|
|
|
|
NamespaceRegistry: m.namespaceRegistry,
|
|
|
|
ServiceRegistry: m.serviceRegistry,
|
|
|
|
|
2016-06-24 15:25:46 +00:00
|
|
|
EndpointReconciler: endpointReconcilerConfig.Reconciler,
|
|
|
|
EndpointInterval: endpointReconcilerConfig.Interval,
|
2015-05-22 22:28:48 +00:00
|
|
|
|
2016-05-05 19:27:49 +00:00
|
|
|
SystemNamespaces: []string{api.NamespaceSystem},
|
|
|
|
SystemNamespacesInterval: 1 * time.Minute,
|
|
|
|
|
2015-05-23 20:41:11 +00:00
|
|
|
ServiceClusterIPRegistry: m.serviceClusterIPAllocator,
|
2015-11-16 21:46:00 +00:00
|
|
|
ServiceClusterIPRange: m.ServiceClusterIPRange,
|
2015-05-23 20:41:11 +00:00
|
|
|
ServiceClusterIPInterval: 3 * time.Minute,
|
|
|
|
|
|
|
|
ServiceNodePortRegistry: m.serviceNodePortAllocator,
|
2015-11-16 21:46:00 +00:00
|
|
|
ServiceNodePortRange: m.ServiceNodePortRange,
|
2015-05-22 22:28:48 +00:00
|
|
|
ServiceNodePortInterval: 3 * time.Minute,
|
2015-05-04 19:11:19 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
PublicIP: m.ClusterIP,
|
2015-05-04 19:11:19 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
ServiceIP: m.ServiceReadWriteIP,
|
|
|
|
ServicePort: m.ServiceReadWritePort,
|
|
|
|
ExtraServicePorts: m.ExtraServicePorts,
|
|
|
|
ExtraEndpointPorts: m.ExtraEndpointPorts,
|
|
|
|
PublicServicePort: m.PublicReadWritePort,
|
2015-10-02 02:59:00 +00:00
|
|
|
KubernetesServiceNodePort: m.KubernetesServiceNodePort,
|
2015-05-03 22:44:05 +00:00
|
|
|
}
|
2014-12-15 20:29:55 +00:00
|
|
|
}
|
|
|
|
|
2015-05-14 00:29:25 +00:00
|
|
|
func (m *Master) getServersToValidate(c *Config) map[string]apiserver.Server {
|
2014-11-02 20:52:31 +00:00
|
|
|
serversToValidate := map[string]apiserver.Server{
|
2014-12-16 03:45:27 +00:00
|
|
|
"controller-manager": {Addr: "127.0.0.1", Port: ports.ControllerManagerPort, Path: "/healthz"},
|
|
|
|
"scheduler": {Addr: "127.0.0.1", Port: ports.SchedulerPort, Path: "/healthz"},
|
2014-11-02 20:52:31 +00:00
|
|
|
}
|
2015-09-30 07:56:51 +00:00
|
|
|
|
2016-03-16 14:17:04 +00:00
|
|
|
for ix, machine := range c.StorageFactory.Backends() {
|
2014-11-02 20:52:31 +00:00
|
|
|
etcdUrl, err := url.Parse(machine)
|
|
|
|
if err != nil {
|
|
|
|
glog.Errorf("Failed to parse etcd url for validation: %v", err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
var port int
|
|
|
|
var addr string
|
|
|
|
if strings.Contains(etcdUrl.Host, ":") {
|
|
|
|
var portString string
|
|
|
|
addr, portString, err = net.SplitHostPort(etcdUrl.Host)
|
|
|
|
if err != nil {
|
|
|
|
glog.Errorf("Failed to split host/port: %s (%v)", etcdUrl.Host, err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
port, _ = strconv.Atoi(portString)
|
|
|
|
} else {
|
|
|
|
addr = etcdUrl.Host
|
|
|
|
port = 4001
|
|
|
|
}
|
2015-12-03 16:09:45 +00:00
|
|
|
// TODO: etcd health checking should be abstracted in the storage tier
|
2016-04-06 03:44:45 +00:00
|
|
|
serversToValidate[fmt.Sprintf("etcd-%d", ix)] = apiserver.Server{
|
|
|
|
Addr: addr,
|
|
|
|
EnableHTTPS: etcdUrl.Scheme == "https",
|
|
|
|
Port: port,
|
|
|
|
Path: "/health",
|
|
|
|
Validate: etcdutil.EtcdHealthCheck,
|
|
|
|
}
|
2014-11-02 20:52:31 +00:00
|
|
|
}
|
|
|
|
return serversToValidate
|
|
|
|
}
|
|
|
|
|
2015-09-09 21:36:19 +00:00
|
|
|
// HasThirdPartyResource returns true if a particular third party resource currently installed.
|
2015-12-08 14:21:04 +00:00
|
|
|
func (m *Master) HasThirdPartyResource(rsrc *extensions.ThirdPartyResource) (bool, error) {
|
2015-09-09 21:36:19 +00:00
|
|
|
_, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc)
|
|
|
|
if err != nil {
|
|
|
|
return false, err
|
|
|
|
}
|
|
|
|
path := makeThirdPartyPath(group)
|
2015-11-16 21:46:00 +00:00
|
|
|
services := m.HandlerContainer.RegisteredWebServices()
|
2015-09-09 21:36:19 +00:00
|
|
|
for ix := range services {
|
|
|
|
if services[ix].RootPath() == path {
|
|
|
|
return true, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Master) removeThirdPartyStorage(path string) error {
|
|
|
|
m.thirdPartyResourcesLock.Lock()
|
|
|
|
defer m.thirdPartyResourcesLock.Unlock()
|
|
|
|
storage, found := m.thirdPartyResources[path]
|
|
|
|
if found {
|
2015-12-10 00:35:35 +00:00
|
|
|
if err := m.removeAllThirdPartyResources(storage.storage); err != nil {
|
2015-09-09 21:36:19 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
delete(m.thirdPartyResources, path)
|
2016-02-03 01:29:17 +00:00
|
|
|
m.RemoveAPIGroupForDiscovery(getThirdPartyGroupName(path))
|
2015-09-09 21:36:19 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveThirdPartyResource removes all resources matching `path`. Also deletes any stored data
|
|
|
|
func (m *Master) RemoveThirdPartyResource(path string) error {
|
|
|
|
if err := m.removeThirdPartyStorage(path); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
services := m.HandlerContainer.RegisteredWebServices()
|
2015-09-09 21:36:19 +00:00
|
|
|
for ix := range services {
|
|
|
|
root := services[ix].RootPath()
|
|
|
|
if root == path || strings.HasPrefix(root, path+"/") {
|
2015-11-16 21:46:00 +00:00
|
|
|
m.HandlerContainer.Remove(services[ix])
|
2015-09-09 21:36:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (m *Master) removeAllThirdPartyResources(registry *thirdpartyresourcedataetcd.REST) error {
|
|
|
|
ctx := api.NewDefaultContext()
|
2015-10-27 13:47:58 +00:00
|
|
|
existingData, err := registry.List(ctx, nil)
|
2015-09-09 21:36:19 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2015-12-08 14:21:04 +00:00
|
|
|
list, ok := existingData.(*extensions.ThirdPartyResourceDataList)
|
2015-09-09 21:36:19 +00:00
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf("expected a *ThirdPartyResourceDataList, got %#v", list)
|
|
|
|
}
|
|
|
|
for ix := range list.Items {
|
|
|
|
item := &list.Items[ix]
|
|
|
|
if _, err := registry.Delete(ctx, item.Name, nil); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ListThirdPartyResources lists all currently installed third party resources
|
|
|
|
func (m *Master) ListThirdPartyResources() []string {
|
|
|
|
m.thirdPartyResourcesLock.RLock()
|
|
|
|
defer m.thirdPartyResourcesLock.RUnlock()
|
|
|
|
result := []string{}
|
|
|
|
for key := range m.thirdPartyResources {
|
|
|
|
result = append(result, key)
|
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
2015-12-10 00:35:35 +00:00
|
|
|
func (m *Master) addThirdPartyResourceStorage(path string, storage *thirdpartyresourcedataetcd.REST, apiGroup unversioned.APIGroup) {
|
2015-09-09 21:36:19 +00:00
|
|
|
m.thirdPartyResourcesLock.Lock()
|
|
|
|
defer m.thirdPartyResourcesLock.Unlock()
|
2015-12-10 00:35:35 +00:00
|
|
|
m.thirdPartyResources[path] = thirdPartyEntry{storage, apiGroup}
|
2016-02-03 01:29:17 +00:00
|
|
|
m.AddAPIGroupForDiscovery(apiGroup)
|
2015-09-09 21:36:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// InstallThirdPartyResource installs a third party resource specified by 'rsrc'. When a resource is
|
|
|
|
// installed a corresponding RESTful resource is added as a valid path in the web service provided by
|
|
|
|
// the master.
|
|
|
|
//
|
|
|
|
// For example, if you install a resource ThirdPartyResource{ Name: "foo.company.com", Versions: {"v1"} }
|
|
|
|
// then the following RESTful resource is created on the server:
|
|
|
|
// http://<host>/apis/company.com/v1/foos/...
|
2015-12-08 14:21:04 +00:00
|
|
|
func (m *Master) InstallThirdPartyResource(rsrc *extensions.ThirdPartyResource) error {
|
2015-08-20 05:08:26 +00:00
|
|
|
kind, group, err := thirdpartyresourcedata.ExtractApiGroupAndKind(rsrc)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2016-05-09 21:47:02 +00:00
|
|
|
plural, _ := meta.KindToResource(unversioned.GroupVersionKind{
|
|
|
|
Group: group,
|
|
|
|
Version: rsrc.Versions[0].Name,
|
|
|
|
Kind: kind,
|
|
|
|
})
|
|
|
|
|
|
|
|
thirdparty := m.thirdpartyapi(group, kind, rsrc.Versions[0].Name, plural.Resource)
|
2015-11-16 21:46:00 +00:00
|
|
|
if err := thirdparty.InstallREST(m.HandlerContainer); err != nil {
|
2015-08-19 18:02:01 +00:00
|
|
|
glog.Fatalf("Unable to setup thirdparty api: %v", err)
|
|
|
|
}
|
2015-09-09 21:36:19 +00:00
|
|
|
path := makeThirdPartyPath(group)
|
2015-11-05 22:52:58 +00:00
|
|
|
groupVersion := unversioned.GroupVersionForDiscovery{
|
2015-09-15 03:55:18 +00:00
|
|
|
GroupVersion: group + "/" + rsrc.Versions[0].Name,
|
|
|
|
Version: rsrc.Versions[0].Name,
|
|
|
|
}
|
2015-10-09 01:33:22 +00:00
|
|
|
apiGroup := unversioned.APIGroup{
|
2016-04-07 22:34:40 +00:00
|
|
|
Name: group,
|
|
|
|
Versions: []unversioned.GroupVersionForDiscovery{groupVersion},
|
|
|
|
PreferredVersion: groupVersion,
|
2015-09-15 03:55:18 +00:00
|
|
|
}
|
2015-12-21 05:27:49 +00:00
|
|
|
apiserver.AddGroupWebService(api.Codecs, m.HandlerContainer, path, apiGroup)
|
2016-05-09 21:47:02 +00:00
|
|
|
|
|
|
|
m.addThirdPartyResourceStorage(path, thirdparty.Storage[plural.Resource].(*thirdpartyresourcedataetcd.REST), apiGroup)
|
2015-12-21 05:27:49 +00:00
|
|
|
apiserver.InstallServiceErrorHandler(api.Codecs, m.HandlerContainer, m.NewRequestInfoResolver(), []string{thirdparty.GroupVersion.String()})
|
2015-08-19 18:02:01 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2016-05-09 21:47:02 +00:00
|
|
|
func (m *Master) thirdpartyapi(group, kind, version, pluralResource string) *apiserver.APIGroupVersion {
|
2016-02-18 13:50:43 +00:00
|
|
|
resourceStorage := thirdpartyresourcedataetcd.NewREST(
|
2016-04-23 19:00:28 +00:00
|
|
|
generic.RESTOptions{
|
|
|
|
Storage: m.thirdPartyStorage,
|
|
|
|
Decorator: generic.UndecoratedStorage,
|
|
|
|
DeleteCollectionWorkers: m.deleteCollectionWorkers,
|
|
|
|
},
|
|
|
|
group,
|
|
|
|
kind,
|
|
|
|
)
|
2015-08-19 18:02:01 +00:00
|
|
|
|
2015-09-29 21:36:47 +00:00
|
|
|
apiRoot := makeThirdPartyPath("")
|
2015-08-19 18:02:01 +00:00
|
|
|
|
|
|
|
storage := map[string]rest.Storage{
|
2016-05-09 21:47:02 +00:00
|
|
|
pluralResource: resourceStorage,
|
2015-08-19 18:02:01 +00:00
|
|
|
}
|
|
|
|
|
2016-01-13 22:40:56 +00:00
|
|
|
optionsExternalVersion := registered.GroupOrDie(api.GroupName).GroupVersion
|
2015-12-21 05:27:49 +00:00
|
|
|
internalVersion := unversioned.GroupVersion{Group: group, Version: runtime.APIVersionInternal}
|
|
|
|
externalVersion := unversioned.GroupVersion{Group: group, Version: version}
|
2015-11-12 20:20:20 +00:00
|
|
|
|
2015-08-19 18:02:01 +00:00
|
|
|
return &apiserver.APIGroupVersion{
|
2015-10-20 17:34:26 +00:00
|
|
|
Root: apiRoot,
|
2015-12-21 05:27:49 +00:00
|
|
|
GroupVersion: externalVersion,
|
2015-11-16 21:46:00 +00:00
|
|
|
RequestInfoResolver: m.NewRequestInfoResolver(),
|
2015-08-19 18:02:01 +00:00
|
|
|
|
2015-09-29 21:36:47 +00:00
|
|
|
Creater: thirdpartyresourcedata.NewObjectCreator(group, version, api.Scheme),
|
2015-08-19 18:02:01 +00:00
|
|
|
Convertor: api.Scheme,
|
2016-04-29 01:21:35 +00:00
|
|
|
Copier: api.Scheme,
|
2015-08-19 18:02:01 +00:00
|
|
|
Typer: api.Scheme,
|
|
|
|
|
2016-01-13 22:40:56 +00:00
|
|
|
Mapper: thirdpartyresourcedata.NewMapper(registered.GroupOrDie(extensions.GroupName).RESTMapper, kind, version, group),
|
|
|
|
Linker: registered.GroupOrDie(extensions.GroupName).SelfLinker,
|
2015-12-08 19:40:23 +00:00
|
|
|
Storage: storage,
|
|
|
|
OptionsExternalVersion: &optionsExternalVersion,
|
2015-08-19 18:02:01 +00:00
|
|
|
|
2016-04-20 17:35:09 +00:00
|
|
|
Serializer: thirdpartyresourcedata.NewNegotiatedSerializer(api.Codecs, kind, externalVersion, internalVersion),
|
|
|
|
ParameterCodec: thirdpartyresourcedata.NewThirdPartyParameterCodec(api.ParameterCodec),
|
2015-12-21 05:27:49 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
Context: m.RequestContextMapper,
|
2015-08-19 18:02:01 +00:00
|
|
|
|
2015-11-16 21:46:00 +00:00
|
|
|
MinRequestTimeout: m.MinRequestTimeout,
|
2015-08-19 18:02:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-16 14:17:04 +00:00
|
|
|
func (m *Master) GetRESTOptionsOrDie(c *Config, resource unversioned.GroupResource) generic.RESTOptions {
|
|
|
|
storage, err := c.StorageFactory.New(resource)
|
|
|
|
if err != nil {
|
|
|
|
glog.Fatalf("Unable to find storage destination for %v, due to %v", resource, err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
return generic.RESTOptions{
|
|
|
|
Storage: storage,
|
|
|
|
Decorator: m.StorageDecorator(),
|
|
|
|
DeleteCollectionWorkers: m.deleteCollectionWorkers,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-16 05:05:51 +00:00
|
|
|
// getExperimentalResources returns the resources for extensions api
|
2015-12-22 21:22:28 +00:00
|
|
|
func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
|
2016-02-22 09:15:22 +00:00
|
|
|
restOptions := func(resource string) generic.RESTOptions {
|
2016-03-16 14:17:04 +00:00
|
|
|
return m.GetRESTOptionsOrDie(c, extensions.Resource(resource))
|
2015-09-30 07:56:51 +00:00
|
|
|
}
|
2016-03-16 14:17:04 +00:00
|
|
|
|
2016-03-22 16:45:23 +00:00
|
|
|
// TODO update when we support more than one version of this group
|
|
|
|
version := extensionsapiv1beta1.SchemeGroupVersion
|
2015-10-13 00:40:37 +00:00
|
|
|
|
|
|
|
storage := map[string]rest.Storage{}
|
2016-02-24 19:22:34 +00:00
|
|
|
|
2016-03-22 16:45:23 +00:00
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) {
|
2016-03-16 14:17:04 +00:00
|
|
|
hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(restOptions("horizontalpodautoscalers"))
|
|
|
|
storage["horizontalpodautoscalers"] = hpaStorage
|
|
|
|
storage["horizontalpodautoscalers/status"] = hpaStatusStorage
|
|
|
|
|
|
|
|
controllerStorage := expcontrolleretcd.NewStorage(m.GetRESTOptionsOrDie(c, api.Resource("replicationControllers")))
|
2015-10-16 08:50:36 +00:00
|
|
|
storage["replicationcontrollers"] = controllerStorage.ReplicationController
|
|
|
|
storage["replicationcontrollers/scale"] = controllerStorage.Scale
|
2015-10-13 00:40:37 +00:00
|
|
|
}
|
2016-03-22 16:45:23 +00:00
|
|
|
thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(restOptions("thirdpartyresources"))
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("thirdpartyresources")) {
|
2015-10-13 00:40:37 +00:00
|
|
|
thirdPartyControl := ThirdPartyController{
|
|
|
|
master: m,
|
|
|
|
thirdPartyResourceRegistry: thirdPartyResourceStorage,
|
|
|
|
}
|
2016-03-24 22:44:31 +00:00
|
|
|
if !m.disableThirdPartyControllerForTesting {
|
|
|
|
go wait.Forever(func() {
|
2015-10-13 00:40:37 +00:00
|
|
|
if err := thirdPartyControl.SyncResources(); err != nil {
|
|
|
|
glog.Warningf("third party resource sync failed: %v", err)
|
|
|
|
}
|
|
|
|
}, 10*time.Second)
|
2016-03-24 22:44:31 +00:00
|
|
|
}
|
2015-10-13 00:40:37 +00:00
|
|
|
storage["thirdpartyresources"] = thirdPartyResourceStorage
|
|
|
|
}
|
|
|
|
|
2016-03-22 16:45:23 +00:00
|
|
|
daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(restOptions("daemonsets"))
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("daemonsets")) {
|
2015-10-13 00:40:37 +00:00
|
|
|
storage["daemonsets"] = daemonSetStorage
|
|
|
|
storage["daemonsets/status"] = daemonSetStatusStorage
|
|
|
|
}
|
2016-03-22 16:45:23 +00:00
|
|
|
deploymentStorage := deploymentetcd.NewStorage(restOptions("deployments"))
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("deployments")) {
|
2015-10-13 00:40:37 +00:00
|
|
|
storage["deployments"] = deploymentStorage.Deployment
|
2015-10-17 01:01:08 +00:00
|
|
|
storage["deployments/status"] = deploymentStorage.Status
|
2016-01-15 02:04:05 +00:00
|
|
|
storage["deployments/rollback"] = deploymentStorage.Rollback
|
2016-03-09 00:27:13 +00:00
|
|
|
storage["deployments/scale"] = deploymentStorage.Scale
|
2015-10-13 00:40:37 +00:00
|
|
|
}
|
2016-03-22 16:45:23 +00:00
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) {
|
2016-03-16 14:17:04 +00:00
|
|
|
jobsStorage, jobsStatusStorage := jobetcd.NewREST(restOptions("jobs"))
|
|
|
|
storage["jobs"] = jobsStorage
|
|
|
|
storage["jobs/status"] = jobsStatusStorage
|
2015-10-13 00:40:37 +00:00
|
|
|
}
|
2016-03-22 16:45:23 +00:00
|
|
|
ingressStorage, ingressStatusStorage := ingressetcd.NewREST(restOptions("ingresses"))
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("ingresses")) {
|
2015-10-24 00:17:55 +00:00
|
|
|
storage["ingresses"] = ingressStorage
|
|
|
|
storage["ingresses/status"] = ingressStatusStorage
|
2015-10-13 00:40:37 +00:00
|
|
|
}
|
2016-03-22 16:45:23 +00:00
|
|
|
podSecurityPolicyStorage := pspetcd.NewREST(restOptions("podsecuritypolicy"))
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("podsecuritypolicy")) {
|
2015-12-14 13:31:23 +00:00
|
|
|
storage["podSecurityPolicies"] = podSecurityPolicyStorage
|
|
|
|
}
|
2016-03-22 16:45:23 +00:00
|
|
|
replicaSetStorage := replicasetetcd.NewStorage(restOptions("replicasets"))
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("replicasets")) {
|
2016-01-19 00:06:57 +00:00
|
|
|
storage["replicasets"] = replicaSetStorage.ReplicaSet
|
|
|
|
storage["replicasets/status"] = replicaSetStorage.Status
|
2016-03-09 00:27:13 +00:00
|
|
|
storage["replicasets/scale"] = replicaSetStorage.Scale
|
2016-01-19 00:06:57 +00:00
|
|
|
}
|
2016-05-18 17:16:33 +00:00
|
|
|
networkPolicyStorage := networkpolicyetcd.NewREST(restOptions("networkpolicies"))
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("networkpolicies")) {
|
|
|
|
storage["networkpolicies"] = networkPolicyStorage
|
|
|
|
}
|
2015-12-15 15:09:42 +00:00
|
|
|
|
2015-12-22 21:22:28 +00:00
|
|
|
return storage
|
2015-07-29 23:15:24 +00:00
|
|
|
}
|
|
|
|
|
2016-02-15 14:00:40 +00:00
|
|
|
// getAutoscalingResources returns the resources for autoscaling api
|
|
|
|
func (m *Master) getAutoscalingResources(c *Config) map[string]rest.Storage {
|
2016-03-22 16:45:23 +00:00
|
|
|
// TODO update when we support more than one version of this group
|
|
|
|
version := autoscalingapiv1.SchemeGroupVersion
|
2016-02-15 14:00:40 +00:00
|
|
|
|
|
|
|
storage := map[string]rest.Storage{}
|
2016-03-22 16:45:23 +00:00
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("horizontalpodautoscalers")) {
|
2016-03-16 14:17:04 +00:00
|
|
|
hpaStorage, hpaStatusStorage := horizontalpodautoscaleretcd.NewREST(m.GetRESTOptionsOrDie(c, autoscaling.Resource("horizontalpodautoscalers")))
|
|
|
|
storage["horizontalpodautoscalers"] = hpaStorage
|
|
|
|
storage["horizontalpodautoscalers/status"] = hpaStatusStorage
|
2016-02-15 14:00:40 +00:00
|
|
|
}
|
|
|
|
return storage
|
|
|
|
}
|
|
|
|
|
2016-04-14 01:45:43 +00:00
|
|
|
// getCertificateResources returns the resources for certificates API
|
|
|
|
func (m *Master) getCertificateResources(c *Config) map[string]rest.Storage {
|
|
|
|
restOptions := func(resource string) generic.RESTOptions {
|
|
|
|
return m.GetRESTOptionsOrDie(c, certificates.Resource(resource))
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO update when we support more than one version of this group
|
|
|
|
version := certificatesapiv1alpha1.SchemeGroupVersion
|
|
|
|
|
|
|
|
storage := map[string]rest.Storage{}
|
|
|
|
|
|
|
|
csrStorage, csrStatusStorage, csrApprovalStorage := certificateetcd.NewREST(restOptions("certificatesigningrequests"))
|
|
|
|
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("certificatesigningrequests")) {
|
|
|
|
storage["certificatesigningrequests"] = csrStorage
|
|
|
|
storage["certificatesigningrequests/status"] = csrStatusStorage
|
|
|
|
storage["certificatesigningrequests/approval"] = csrApprovalStorage
|
|
|
|
}
|
|
|
|
|
|
|
|
return storage
|
|
|
|
}
|
|
|
|
|
2016-02-17 17:11:31 +00:00
|
|
|
// getBatchResources returns the resources for batch api
|
2016-04-25 12:47:50 +00:00
|
|
|
func (m *Master) getBatchResources(c *Config, version unversioned.GroupVersion) map[string]rest.Storage {
|
2016-02-17 17:11:31 +00:00
|
|
|
storage := map[string]rest.Storage{}
|
2016-03-22 16:45:23 +00:00
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("jobs")) {
|
2016-03-16 14:17:04 +00:00
|
|
|
jobsStorage, jobsStatusStorage := jobetcd.NewREST(m.GetRESTOptionsOrDie(c, batch.Resource("jobs")))
|
|
|
|
storage["jobs"] = jobsStorage
|
|
|
|
storage["jobs/status"] = jobsStatusStorage
|
2016-02-17 17:11:31 +00:00
|
|
|
}
|
|
|
|
return storage
|
|
|
|
}
|
|
|
|
|
2016-05-07 00:03:43 +00:00
|
|
|
// getPolicyResources returns the resources for policy api
|
|
|
|
func (m *Master) getPolicyResources(c *Config) map[string]rest.Storage {
|
|
|
|
// TODO update when we support more than one version of this group
|
|
|
|
version := policyapiv1alpha1.SchemeGroupVersion
|
|
|
|
|
|
|
|
storage := map[string]rest.Storage{}
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("poddisruptionbudgets")) {
|
|
|
|
poddisruptionbudgetStorage, poddisruptionbudgetStatusStorage := poddisruptionbudgetetcd.NewREST(m.GetRESTOptionsOrDie(c, policy.Resource("poddisruptionbudgets")))
|
|
|
|
storage["poddisruptionbudgets"] = poddisruptionbudgetStorage
|
|
|
|
storage["poddisruptionbudgets/status"] = poddisruptionbudgetStatusStorage
|
|
|
|
}
|
|
|
|
return storage
|
|
|
|
}
|
|
|
|
|
2016-05-18 17:16:33 +00:00
|
|
|
// getAppsResources returns the resources for apps api
|
2016-04-15 22:30:15 +00:00
|
|
|
func (m *Master) getAppsResources(c *Config) map[string]rest.Storage {
|
|
|
|
// TODO update when we support more than one version of this group
|
|
|
|
version := appsapi.SchemeGroupVersion
|
|
|
|
|
|
|
|
storage := map[string]rest.Storage{}
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("petsets")) {
|
2016-03-16 14:17:04 +00:00
|
|
|
petsetStorage, petsetStatusStorage := petsetetcd.NewREST(m.GetRESTOptionsOrDie(c, apps.Resource("petsets")))
|
2016-04-15 22:30:15 +00:00
|
|
|
storage["petsets"] = petsetStorage
|
|
|
|
storage["petsets/status"] = petsetStatusStorage
|
|
|
|
}
|
|
|
|
return storage
|
|
|
|
}
|
|
|
|
|
2016-05-25 21:20:41 +00:00
|
|
|
func (m *Master) getRBACResources(c *Config) map[string]rest.Storage {
|
|
|
|
version := rbacapi.SchemeGroupVersion
|
|
|
|
|
|
|
|
once := new(sync.Once)
|
|
|
|
var authorizationRuleResolver rbacvalidation.AuthorizationRuleResolver
|
|
|
|
newRuleValidator := func() rbacvalidation.AuthorizationRuleResolver {
|
|
|
|
once.Do(func() {
|
|
|
|
authorizationRuleResolver = rbacvalidation.NewDefaultRuleResolver(
|
|
|
|
role.NewRegistry(roleetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("roles")))),
|
|
|
|
rolebinding.NewRegistry(rolebindingetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("rolebindings")))),
|
|
|
|
clusterrole.NewRegistry(clusterroleetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("clusterroles")))),
|
|
|
|
clusterrolebinding.NewRegistry(clusterrolebindingetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("clusterrolebindings")))),
|
|
|
|
)
|
|
|
|
})
|
|
|
|
return authorizationRuleResolver
|
|
|
|
}
|
|
|
|
|
|
|
|
storage := map[string]rest.Storage{}
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("roles")) {
|
|
|
|
rolesStorage := roleetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("roles")))
|
|
|
|
storage["roles"] = rolepolicybased.NewStorage(rolesStorage, newRuleValidator(), c.AuthorizerRBACSuperUser)
|
|
|
|
}
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("rolebindings")) {
|
|
|
|
roleBindingsStorage := rolebindingetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("rolebindings")))
|
|
|
|
storage["rolebindings"] = rolebindingpolicybased.NewStorage(roleBindingsStorage, newRuleValidator(), c.AuthorizerRBACSuperUser)
|
|
|
|
}
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("clusterroles")) {
|
|
|
|
clusterRolesStorage := clusterroleetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("clusterroles")))
|
|
|
|
storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, newRuleValidator(), c.AuthorizerRBACSuperUser)
|
|
|
|
}
|
|
|
|
if c.APIResourceConfigSource.ResourceEnabled(version.WithResource("clusterrolebindings")) {
|
|
|
|
clusterRoleBindingsStorage := clusterrolebindingetcd.NewREST(m.GetRESTOptionsOrDie(c, rbac.Resource("clusterrolebindings")))
|
|
|
|
storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, newRuleValidator(), c.AuthorizerRBACSuperUser)
|
|
|
|
}
|
|
|
|
return storage
|
|
|
|
}
|
|
|
|
|
2015-07-28 08:10:48 +00:00
|
|
|
// findExternalAddress returns ExternalIP of provided node with fallback to LegacyHostIP.
|
2015-05-28 04:38:21 +00:00
|
|
|
func findExternalAddress(node *api.Node) (string, error) {
|
2015-07-28 08:10:48 +00:00
|
|
|
var fallback string
|
2015-05-28 04:38:21 +00:00
|
|
|
for ix := range node.Status.Addresses {
|
|
|
|
addr := &node.Status.Addresses[ix]
|
|
|
|
if addr.Type == api.NodeExternalIP {
|
|
|
|
return addr.Address, nil
|
|
|
|
}
|
2015-07-28 08:10:48 +00:00
|
|
|
if fallback == "" && addr.Type == api.NodeLegacyHostIP {
|
|
|
|
fallback = addr.Address
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if fallback != "" {
|
|
|
|
return fallback, nil
|
2015-05-28 04:38:21 +00:00
|
|
|
}
|
|
|
|
return "", fmt.Errorf("Couldn't find external address: %v", node)
|
|
|
|
}
|
|
|
|
|
2015-06-02 16:52:35 +00:00
|
|
|
func (m *Master) getNodeAddresses() ([]string, error) {
|
2015-10-27 13:47:58 +00:00
|
|
|
nodes, err := m.nodeRegistry.ListNodes(api.NewDefaultContext(), nil)
|
2015-05-28 04:38:21 +00:00
|
|
|
if err != nil {
|
2015-06-02 16:52:35 +00:00
|
|
|
return nil, err
|
2015-05-28 04:38:21 +00:00
|
|
|
}
|
2015-06-02 16:52:35 +00:00
|
|
|
addrs := []string{}
|
2015-05-28 04:38:21 +00:00
|
|
|
for ix := range nodes.Items {
|
|
|
|
node := &nodes.Items[ix]
|
|
|
|
addr, err := findExternalAddress(node)
|
|
|
|
if err != nil {
|
2015-06-02 16:52:35 +00:00
|
|
|
return nil, err
|
2015-05-28 04:38:21 +00:00
|
|
|
}
|
2015-06-02 16:52:35 +00:00
|
|
|
addrs = append(addrs, addr)
|
2015-05-28 04:38:21 +00:00
|
|
|
}
|
2015-06-02 16:52:35 +00:00
|
|
|
return addrs, nil
|
|
|
|
}
|
2015-05-28 04:38:21 +00:00
|
|
|
|
2015-07-14 19:30:43 +00:00
|
|
|
func (m *Master) IsTunnelSyncHealthy(req *http.Request) error {
|
2015-10-09 05:18:16 +00:00
|
|
|
if m.tunneler == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
lag := m.tunneler.SecondsSinceSync()
|
2015-07-14 19:30:43 +00:00
|
|
|
if lag > 600 {
|
|
|
|
return fmt.Errorf("Tunnel sync is taking to long: %d", lag)
|
|
|
|
}
|
2016-03-18 00:57:04 +00:00
|
|
|
sshKeyLag := m.tunneler.SecondsSinceSSHKeySync()
|
|
|
|
if sshKeyLag > 600 {
|
|
|
|
return fmt.Errorf("SSHKey sync is taking to long: %d", sshKeyLag)
|
|
|
|
}
|
2015-07-14 19:30:43 +00:00
|
|
|
return nil
|
|
|
|
}
|
2016-03-22 16:45:23 +00:00
|
|
|
|
|
|
|
func DefaultAPIResourceConfigSource() *genericapiserver.ResourceConfig {
|
|
|
|
ret := genericapiserver.NewResourceConfig()
|
2016-04-14 01:45:43 +00:00
|
|
|
ret.EnableVersions(apiv1.SchemeGroupVersion, extensionsapiv1beta1.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, autoscalingapiv1.SchemeGroupVersion, appsapi.SchemeGroupVersion, policyapiv1alpha1.SchemeGroupVersion, rbacapi.SchemeGroupVersion, certificatesapiv1alpha1.SchemeGroupVersion)
|
2016-03-22 16:45:23 +00:00
|
|
|
|
|
|
|
// all extensions resources except these are disabled by default
|
|
|
|
ret.EnableResources(
|
|
|
|
extensionsapiv1beta1.SchemeGroupVersion.WithResource("daemonsets"),
|
|
|
|
extensionsapiv1beta1.SchemeGroupVersion.WithResource("deployments"),
|
|
|
|
extensionsapiv1beta1.SchemeGroupVersion.WithResource("horizontalpodautoscalers"),
|
|
|
|
extensionsapiv1beta1.SchemeGroupVersion.WithResource("ingresses"),
|
|
|
|
extensionsapiv1beta1.SchemeGroupVersion.WithResource("jobs"),
|
|
|
|
extensionsapiv1beta1.SchemeGroupVersion.WithResource("replicasets"),
|
|
|
|
extensionsapiv1beta1.SchemeGroupVersion.WithResource("thirdpartyresources"),
|
|
|
|
)
|
|
|
|
|
|
|
|
return ret
|
|
|
|
}
|