Initial work on UAS

This commit is contained in:
Justin Santa Barbara 2017-02-12 15:48:22 -05:00 committed by Kris Nova
parent 7f89d6e17d
commit 8b4ce49e9b
13 changed files with 460 additions and 17 deletions

46
cmd/kops-server/main.go Normal file
View File

@ -0,0 +1,46 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"flag"
"os"
"runtime"
"k8s.io/kops/pkg/apiserver/cmd/server"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/util/logs"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UTC().UnixNano())
logs.InitLogs()
defer logs.FlushLogs()
if len(os.Getenv("GOMAXPROCS")) == 0 {
runtime.GOMAXPROCS(runtime.NumCPU())
}
cmd := server.NewCommandStartKopsServer(os.Stdout, os.Stderr)
cmd.Flags().AddGoFlagSet(flag.CommandLine)
if err := cmd.Execute(); err != nil {
cmdutil.CheckErr(err)
}
}

View File

@ -22,10 +22,7 @@ import (
"crypto/rsa"
"fmt"
"github.com/golang/glog"
apierrors "k8s.io/apimachinery/pkg/api/errors"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/kops/federation/model"
"k8s.io/kops/federation/targets/kubernetestarget"
"k8s.io/kops/federation/tasks"
@ -36,7 +33,7 @@ import (
"k8s.io/kops/upup/pkg/fi/fitasks"
"k8s.io/kops/upup/pkg/fi/k8sapi"
"k8s.io/kops/upup/pkg/kutil"
federation_clientset "k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
"k8s.io/kubernetes/federation/client/clientset_generated/federation_clientset"
k8sapiv1 "k8s.io/kubernetes/pkg/api/v1"
"strings"
"text/template"
@ -146,10 +143,10 @@ func (o *ApplyFederationOperation) Run() error {
if err != nil {
return err
}
//k8sControllerClient, err := release_1_5.NewForConfig(federationRestConfig)
//if err != nil {
// return err
//}
k8sClient, err := kubernetes.NewForConfig(federationRestConfig)
if err != nil {
return err
}
for _, member := range o.Federation.Spec.Members {
glog.V(2).Infof("configuring member cluster %q", member)
@ -178,7 +175,7 @@ func (o *ApplyFederationOperation) Run() error {
// Create default namespace
glog.V(2).Infof("Ensuring default namespace exists")
if _, err := o.ensureFederationNamespace(federationControllerClient, "default"); err != nil {
if _, err := o.ensureFederationNamespace(k8sClient, "default"); err != nil {
return err
}
@ -362,7 +359,7 @@ func (o *ApplyFederationOperation) executeTemplate(key string, templateDefinitio
func (o *ApplyFederationOperation) EnsureNamespace(c *fi.Context) error {
k8s := c.Target.(*kubernetestarget.KubernetesTarget).KubernetesClient
ns, err := k8s.Core().Namespaces().Get(o.namespace, meta_v1.GetOptions{})
ns, err := k8s.CoreV1().Namespaces().Get(o.namespace, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
ns = nil

View File

@ -60,7 +60,7 @@ func mutateNamespace(k8s federation_clientset.Interface, name string, fn func(s
return created, nil
} else {
glog.V(2).Infof("updating federation Namespace %s", name)
created, err := k8s.Core().Namespaces().Update(updated)
created, err := k8s.CoreV1().Namespaces().Update(updated)
if err != nil {
return nil, fmt.Errorf("error updating federation Namespace %s: %v", name, err)
}

View File

@ -42,8 +42,8 @@ func Install(groupFactoryRegistry announced.APIGroupFactoryRegistry, registry *r
v1alpha2.SchemeGroupVersion.Version,
v1alpha1.SchemeGroupVersion.Version,
},
ImportPrefix: "k8s.io/kops/pkg/apis/kops",
// ?? RootScopedKinds: sets.NewString("NodeMetrics"),
RootScopedKinds: sets.NewString("Cluster"),
ImportPrefix: "k8s.io/kops/pkg/apis/kops",
AddInternalObjectsToScheme: kops.AddToScheme,
},
announced.VersionToSchemeFunc{

View File

@ -63,6 +63,7 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&Federation{},
&FederationList{},
)
//metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}

View File

@ -16,4 +16,6 @@ limitations under the License.
// +k8s:conversion-gen=k8s.io/kops/pkg/apis/kops
// +k8s:defaulter-gen=TypeMeta
// +groupName=kops
package v1alpha1

View File

@ -16,4 +16,6 @@ limitations under the License.
// +k8s:conversion-gen=k8s.io/kops/pkg/apis/kops
// +k8s:defaulter-gen=TypeMeta
// +groupName=kops
package v1alpha2 // import "k8s.io/kops/pkg/apis/kops/v1alpha2"

View File

@ -0,0 +1,86 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package apiserver
import (
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/apiserver/pkg/server"
"k8s.io/kubernetes/pkg/version"
"k8s.io/kops/pkg/apis/kops"
_ "k8s.io/kops/pkg/apis/kops/install"
"k8s.io/kops/pkg/apis/kops/v1alpha2"
"k8s.io/kops/pkg/apiserver/registry/cluster"
"k8s.io/kubernetes/pkg/api"
)
type Config struct {
GenericConfig *server.Config
// RESTOptionsGetter is used to construct storage for a particular resource
RESTOptionsGetter generic.RESTOptionsGetter
}
// APIDiscoveryServer contains state for a Kubernetes cluster master/api server.
type APIDiscoveryServer struct {
GenericAPIServer *server.GenericAPIServer
}
type completedConfig struct {
*Config
}
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
func (c *Config) Complete() completedConfig {
c.GenericConfig.Complete()
version := version.Get()
c.GenericConfig.Version = &version
return completedConfig{c}
}
// SkipComplete provides a way to construct a server instance without config completion.
func (c *Config) SkipComplete() completedConfig {
return completedConfig{c}
}
// New returns a new instance of APIDiscoveryServer from the given config.
func (c completedConfig) New() (*APIDiscoveryServer, error) {
genericServer, err := c.Config.GenericConfig.SkipComplete().New() // completion is done in Complete, no need for a second time
if err != nil {
return nil, err
}
s := &APIDiscoveryServer{
GenericAPIServer: genericServer,
}
apiGroupInfo := server.NewDefaultAPIGroupInfo(kops.GroupName, api.Registry, api.Scheme, api.ParameterCodec, api.Codecs)
apiGroupInfo.GroupMeta.GroupVersion = v1alpha2.SchemeGroupVersion
v1alpha2storage := map[string]rest.Storage{}
v1alpha2storage["clusters"] = cluster.NewREST(c.RESTOptionsGetter)
apiGroupInfo.VersionedResourcesStorageMap["v1alpha2"] = v1alpha2storage
if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
return nil, err
}
return s, nil
}

View File

@ -0,0 +1,157 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package server
import (
"io"
"github.com/pborman/uuid"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/registry/generic/registry"
genericapiserver "k8s.io/apiserver/pkg/server"
genericoptions "k8s.io/apiserver/pkg/server/options"
"k8s.io/apiserver/pkg/storage/storagebackend"
"k8s.io/kubernetes/pkg/api"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kops/pkg/apiserver"
//"k8s.io/kops/pkg/apis/kops/v1alpha1"
"k8s.io/kops/pkg/apis/kops/v1alpha2"
"github.com/golang/glog"
)
const defaultEtcdPathPrefix = "/registry/kops.kubernetes.io"
type KopsServerOptions struct {
Etcd *genericoptions.EtcdOptions
//SecureServing *genericoptions.SecureServingOptions
InsecureServing *genericoptions.ServingOptions
Authentication *genericoptions.DelegatingAuthenticationOptions
Authorization *genericoptions.DelegatingAuthorizationOptions
StdOut io.Writer
StdErr io.Writer
}
// NewCommandStartKopsServer provides a CLI handler for 'start master' command
func NewCommandStartKopsServer(out, err io.Writer) *cobra.Command {
o := &KopsServerOptions{
Etcd: genericoptions.NewEtcdOptions(
defaultEtcdPathPrefix,
api.Scheme,
nil,
),
//SecureServing: genericoptions.NewSecureServingOptions(),
InsecureServing: genericoptions.NewInsecureServingOptions(),
Authentication: genericoptions.NewDelegatingAuthenticationOptions(),
Authorization: genericoptions.NewDelegatingAuthorizationOptions(),
StdOut: out,
StdErr: err,
}
o.Etcd.StorageConfig.Type = storagebackend.StorageTypeETCD2
o.Etcd.StorageConfig.Codec = api.Codecs.LegacyCodec(v1alpha2.SchemeGroupVersion)
//o.SecureServing.ServingOptions.BindPort = 443
cmd := &cobra.Command{
Short: "Launch a kops API server",
Long: "Launch a kops API server",
Run: func(c *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete())
cmdutil.CheckErr(o.Validate(args))
cmdutil.CheckErr(o.RunKopsServer())
},
}
flags := cmd.Flags()
o.Etcd.AddFlags(flags)
//o.SecureServing.AddFlags(flags)
o.InsecureServing.AddFlags(flags)
o.Authentication.AddFlags(flags)
o.Authorization.AddFlags(flags)
return cmd
}
func (o KopsServerOptions) Validate(args []string) error {
return nil
}
func (o *KopsServerOptions) Complete() error {
return nil
}
func (o KopsServerOptions) RunKopsServer() error {
// TODO have a "real" external address
//if err := o.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost"); err != nil {
// return fmt.Errorf("error creating self-signed certificates: %v", err)
//}
genericAPIServerConfig := genericapiserver.NewConfig().WithSerializer(api.Codecs)
//if err := o.SecureServing.ApplyTo(genericAPIServerConfig); err != nil {
// return err
//}
if err := o.InsecureServing.ApplyTo(genericAPIServerConfig); err != nil {
return err
}
glog.Warningf("Authentication/Authorization disabled")
//if _, err := genericAPIServerConfig.ApplyDelegatingAuthenticationOptions(o.Authentication); err != nil {
// return err
//}
//if _, err := genericAPIServerConfig.ApplyDelegatingAuthorizationOptions(o.Authorization); err != nil {
// return err
//}
var err error
privilegedLoopbackToken := uuid.NewRandom().String()
if genericAPIServerConfig.LoopbackClientConfig, err = genericAPIServerConfig.SecureServingInfo.NewSelfClientConfig(privilegedLoopbackToken); err != nil {
return err
}
config := apiserver.Config{
GenericConfig: genericAPIServerConfig,
RESTOptionsGetter: &restOptionsFactory{storageConfig: &o.Etcd.StorageConfig},
}
server, err := config.Complete().New()
if err != nil {
return err
}
server.GenericAPIServer.PrepareRun().Run(wait.NeverStop)
return nil
}
type restOptionsFactory struct {
storageConfig *storagebackend.Config
}
func (f *restOptionsFactory) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
return generic.RESTOptions{
StorageConfig: f.storageConfig,
Decorator: registry.StorageWithCacher,
DeleteCollectionWorkers: 1,
EnableGarbageCollection: false,
ResourcePrefix: f.storageConfig.Prefix + "/" + resource.Group + "/" + resource.Resource,
}, nil
}

View File

@ -0,0 +1,58 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cluster
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kops/pkg/apis/kops"
)
// rest implements a RESTStorage for kops Clusters against etcd
type REST struct {
*genericregistry.Store
}
// NewREST returns a RESTStorage object that will work against kops Clusters.
func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
store := &genericregistry.Store{
Copier: api.Scheme,
NewFunc: func() runtime.Object {
return &kops.Cluster{}
},
NewListFunc: func() runtime.Object {
return &kops.ClusterList{}
},
ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*kops.Cluster).ObjectMeta.Name, nil
},
PredicateFunc: MatchCluster,
QualifiedResource: kops.Resource("clusters"),
CreateStrategy: Strategy,
UpdateStrategy: Strategy,
DeleteStrategy: Strategy,
}
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: GetAttrs}
if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up
}
return &REST{store}
}

View File

@ -0,0 +1,94 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cluster
import (
"fmt"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/generic"
"k8s.io/apiserver/pkg/storage"
"k8s.io/apiserver/pkg/storage/names"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kops/pkg/apis/kops"
)
type clusterStrategy struct {
runtime.ObjectTyper
names.NameGenerator
}
var Strategy = clusterStrategy{kapi.Scheme, names.SimpleNameGenerator}
func (clusterStrategy) NamespaceScoped() bool {
return false
}
func (clusterStrategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
}
func (clusterStrategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
}
func (clusterStrategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
return field.ErrorList{}
// return validation.ValidateServiceInjection(obj.(*serviceinjection.ServiceInjection))
}
func (clusterStrategy) AllowCreateOnUpdate() bool {
return false
}
func (clusterStrategy) AllowUnconditionalUpdate() bool {
return false
}
func (clusterStrategy) Canonicalize(obj runtime.Object) {
}
func (clusterStrategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
return field.ErrorList{}
// return validation.ValidateServiceInjectionUpdate(obj.(*serviceinjection.ServiceInjection), old.(*serviceinjection.ServiceInjection))
}
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
cluster, ok := obj.(*kops.Cluster)
if !ok {
return nil, nil, fmt.Errorf("given object is not a Cluster.")
}
return labels.Set(cluster.ObjectMeta.Labels), ClusterToSelectableFields(cluster), nil
}
// MatchCluster is the filter used by the generic etcd backend to watch events
// from etcd to clients of the apiserver only interested in specific labels/fields.
func MatchCluster(label labels.Selector, field fields.Selector) storage.SelectionPredicate {
return storage.SelectionPredicate{
Label: label,
Field: field,
GetAttrs: GetAttrs,
}
}
// ClusterToSelectableFields returns a field set that represents the object.
func ClusterToSelectableFields(obj *kops.Cluster) fields.Set {
return generic.ObjectMetaFieldsSet(&obj.ObjectMeta, true)
}

View File

@ -23,7 +23,7 @@ import (
"fmt"
"github.com/golang/glog"
apierrors "k8s.io/apimachinery/pkg/api/errors"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/kops/upup/pkg/fi"
@ -79,7 +79,7 @@ func (c *KubernetesKeystore) issueCert(id string, serial *big.Int, privateKey *f
}
func (c *KubernetesKeystore) findSecret(id string) (*v1.Secret, error) {
secret, err := c.client.CoreV1().Secrets(c.namespace).Get(id, meta_v1.GetOptions{})
secret, err := c.client.CoreV1().Secrets(c.namespace).Get(id, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return nil, nil

View File

@ -80,8 +80,8 @@ func (b *KubeconfigBuilder) DeleteKubeConfig() error {
}
// Create new Rest Client
func (c *KubeconfigBuilder) BuildRestConfig() (*restclient.Config, error) {
restConfig := &restclient.Config{
func (c *KubeconfigBuilder) BuildRestConfig() (*rest.Config, error) {
restConfig := &rest.Config{
Host: "https://" + c.KubeMasterIP,
}
restConfig.CAData = c.CACert