未验证 提交 641615b2 编写于 作者: Z zryfish 提交者: GitHub

This is a huge commit, it does following things: (#1942)

1. Remove ks-iam standalone binary, move it to ks-apiserver
2. Generate all devops apis inside kubesphere repository, no need to
import s2ioperator.
3. Reorganize ldap code, make it more flexible to use.
上级 7270307b
......@@ -9,8 +9,7 @@ git:
depth: false
go:
- "1.12.x"
- "tip"
- "1.13.x"
env:
- GO111MODULE=on
cache:
......@@ -23,11 +22,10 @@ before_script:
script:
- diff -u <(echo -n) <(gofmt -d ./pkg ./cmd ./tools)
- make openapi
- make all
before_install:
- go get -t -v ./...
- go mod vendor
after_success:
- bash <(curl -s https://codecov.io/bash)
......
......@@ -39,7 +39,7 @@ define ALL_HELP_INFO
# debugging tools like delve.
endef
.PHONY: all
all: test hypersphere ks-apiserver ks-apigateway ks-iam controller-manager
all: test hypersphere ks-apiserver ks-apigateway controller-manager
# Build ks-apiserver binary
ks-apiserver: fmt vet
......@@ -49,10 +49,6 @@ ks-apiserver: fmt vet
ks-apigateway: fmt vet
hack/gobuild.sh cmd/ks-apigateway
# Build ks-iam binary
ks-iam: fmt vet
hack/gobuild.sh cmd/ks-iam
# Build controller-manager binary
controller-manager: fmt vet
hack/gobuild.sh cmd/controller-manager
......
......@@ -24,7 +24,27 @@ API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,Table
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,TableRow,Cells
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,TableRow,Conditions
API rule violation: list_type_missing,k8s.io/apimachinery/pkg/apis/meta/v1,UpdateOptions,DryRun
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,ContainerConfig,Env
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,ContainerInfo,BuildVolumes
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,ContainerInfo,RuntimeArtifacts
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,Parameter,OptValues
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iAutoScale,Containers
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBinaryList,Items
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBuildResult,ImageRepoTags
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBuilderList,Items
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBuilderTemplateList,Items
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBuilderTemplateSpec,ContainerInfo
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBuilderTemplateSpec,Parameters
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,AddHost
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,BuildVolumes
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,DropCapabilities
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,Environment
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,Injections
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,NodeAffinityValues
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,RuntimeArtifacts
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,SecurityOpt
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iRunList,Items
API rule violation: list_type_missing,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,UserDefineTemplate,Parameters
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,APIResourceList,APIResources
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,Duration,Duration
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,InternalEvent,Object
......@@ -32,4 +52,13 @@ API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,InternalEve
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,MicroTime,Time
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,StatusCause,Type
API rule violation: names_match,k8s.io/apimachinery/pkg/apis/meta/v1,Time,Time
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,ContainerConfig,Env
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,ContainerConfig,Labels
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,DockerConfig,Endpoint
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBinarySpec,MD5
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iBuilderTemplateSpec,Parameters
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,CGroupLimits
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,CallbackURL
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,ImageScriptsURL
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,ScriptsURL
API rule violation: names_match,kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1,S2iConfig,SourceURL
......@@ -18,122 +18,74 @@
package app
import (
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/controller/application"
"kubesphere.io/kubesphere/pkg/controller/destinationrule"
"kubesphere.io/kubesphere/pkg/controller/job"
"kubesphere.io/kubesphere/pkg/controller/s2ibinary"
"kubesphere.io/kubesphere/pkg/controller/s2irun"
"kubesphere.io/kubesphere/pkg/controller/storage/expansion"
//"kubesphere.io/kubesphere/pkg/controller/job"
"kubesphere.io/kubesphere/pkg/controller/virtualservice"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"sigs.k8s.io/controller-runtime/pkg/manager"
"time"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
applicationclientset "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned"
applicationinformers "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
s2iclientset "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
s2iinformers "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
istioclientset "istio.io/client-go/pkg/clientset/versioned"
istioinformers "istio.io/client-go/pkg/informers/externalversions"
kubesphereclientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
kubesphereinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
)
const defaultResync = 600 * time.Second
var log = logf.Log.WithName("controller-manager")
func AddControllers(mgr manager.Manager, cfg *rest.Config, stopCh <-chan struct{}) error {
kubeClient, err := kubernetes.NewForConfig(cfg)
if err != nil {
log.Error(err, "building kubernetes client failed")
}
istioclient, err := istioclientset.NewForConfig(cfg)
if err != nil {
log.Error(err, "create istio client failed")
return err
}
applicationClient, err := applicationclientset.NewForConfig(cfg)
if err != nil {
log.Error(err, "create application client failed")
return err
}
s2iclient, err := s2iclientset.NewForConfig(cfg)
if err != nil {
log.Error(err, "create s2i client failed")
return err
}
kubesphereclient, err := kubesphereclientset.NewForConfig(cfg)
if err != nil {
log.Error(err, "create kubesphere client failed")
return err
}
informerFactory := informers.NewSharedInformerFactory(kubeClient, defaultResync)
istioInformer := istioinformers.NewSharedInformerFactory(istioclient, defaultResync)
applicationInformer := applicationinformers.NewSharedInformerFactory(applicationClient, defaultResync)
s2iInformer := s2iinformers.NewSharedInformerFactory(s2iclient, defaultResync)
func AddControllers(
mgr manager.Manager,
client k8s.Client,
informerFactory informers.InformerFactory,
stopCh <-chan struct{}) error {
kubesphereInformer := kubesphereinformers.NewSharedInformerFactory(kubesphereclient, defaultResync)
kubernetesInformer := informerFactory.KubernetesSharedInformerFactory()
istioInformer := informerFactory.IstioSharedInformerFactory()
kubesphereInformer := informerFactory.KubeSphereSharedInformerFactory()
applicationInformer := informerFactory.ApplicationSharedInformerFactory()
vsController := virtualservice.NewVirtualServiceController(informerFactory.Core().V1().Services(),
vsController := virtualservice.NewVirtualServiceController(kubernetesInformer.Core().V1().Services(),
istioInformer.Networking().V1alpha3().VirtualServices(),
istioInformer.Networking().V1alpha3().DestinationRules(),
kubesphereInformer.Servicemesh().V1alpha2().Strategies(),
kubeClient,
istioclient,
kubesphereclient)
client.Kubernetes(),
client.Istio(),
client.KubeSphere())
drController := destinationrule.NewDestinationRuleController(informerFactory.Apps().V1().Deployments(),
drController := destinationrule.NewDestinationRuleController(kubernetesInformer.Apps().V1().Deployments(),
istioInformer.Networking().V1alpha3().DestinationRules(),
informerFactory.Core().V1().Services(),
kubernetesInformer.Core().V1().Services(),
kubesphereInformer.Servicemesh().V1alpha2().ServicePolicies(),
kubeClient,
istioclient,
kubesphereclient)
client.Kubernetes(),
client.Istio(),
client.KubeSphere())
apController := application.NewApplicationController(informerFactory.Core().V1().Services(),
informerFactory.Apps().V1().Deployments(),
informerFactory.Apps().V1().StatefulSets(),
apController := application.NewApplicationController(kubernetesInformer.Core().V1().Services(),
kubernetesInformer.Apps().V1().Deployments(),
kubernetesInformer.Apps().V1().StatefulSets(),
kubesphereInformer.Servicemesh().V1alpha2().Strategies(),
kubesphereInformer.Servicemesh().V1alpha2().ServicePolicies(),
applicationInformer.App().V1beta1().Applications(),
kubeClient,
applicationClient)
client.Kubernetes(),
client.Application())
jobController := job.NewJobController(informerFactory.Batch().V1().Jobs(), kubeClient)
jobController := job.NewJobController(kubernetesInformer.Batch().V1().Jobs(), client.Kubernetes())
s2iBinaryController := s2ibinary.NewController(kubesphereclient,
kubeClient,
s2iBinaryController := s2ibinary.NewController(client.KubeSphere(),
client.Kubernetes(),
kubesphereInformer.Devops().V1alpha1().S2iBinaries())
s2iRunController := s2irun.NewController(kubesphereclient, s2iclient, kubeClient,
s2iRunController := s2irun.NewS2iRunController(client.KubeSphere(),
client.Kubernetes(),
kubesphereInformer.Devops().V1alpha1().S2iBinaries(),
s2iInformer.Devops().V1alpha1().S2iRuns())
kubesphereInformer.Devops().V1alpha1().S2iRuns())
volumeExpansionController := expansion.NewVolumeExpansionController(
kubeClient,
informerFactory.Core().V1().PersistentVolumeClaims(),
informerFactory.Storage().V1().StorageClasses(),
informerFactory.Core().V1().Pods(),
informerFactory.Apps().V1().Deployments(),
informerFactory.Apps().V1().ReplicaSets(),
informerFactory.Apps().V1().StatefulSets())
kubesphereInformer.Start(stopCh)
istioInformer.Start(stopCh)
informerFactory.Start(stopCh)
applicationInformer.Start(stopCh)
s2iInformer.Start(stopCh)
client.Kubernetes(),
kubernetesInformer.Core().V1().PersistentVolumeClaims(),
kubernetesInformer.Storage().V1().StorageClasses(),
kubernetesInformer.Core().V1().Pods(),
kubernetesInformer.Apps().V1().Deployments(),
kubernetesInformer.Apps().V1().ReplicaSets(),
kubernetesInformer.Apps().V1().StatefulSets())
controllers := map[string]manager.Runnable{
"virtualservice-controller": vsController,
......@@ -146,9 +98,8 @@ func AddControllers(mgr manager.Manager, cfg *rest.Config, stopCh <-chan struct{
}
for name, ctrl := range controllers {
err = mgr.Add(ctrl)
if err != nil {
log.Error(err, "add controller to manager failed", "name", name)
if err := mgr.Add(ctrl); err != nil {
klog.Error(err, "add controller to manager failed", "name", name)
return err
}
}
......
......@@ -6,9 +6,10 @@ import (
"k8s.io/client-go/tools/leaderelection"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog"
kubesphereconfig "kubesphere.io/kubesphere/pkg/server/config"
kubesphereconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/simple/client/s3"
"strings"
......@@ -20,6 +21,7 @@ type KubeSphereControllerManagerOptions struct {
DevopsOptions *jenkins.Options
S3Options *s3.Options
OpenPitrixOptions *openpitrix.Options
KubeSphereOptions *kubesphere.Options
LeaderElection *leaderelection.LeaderElectionConfig
}
......@@ -30,6 +32,7 @@ func NewKubeSphereControllerManagerOptions() *KubeSphereControllerManagerOptions
DevopsOptions: jenkins.NewDevopsOptions(),
S3Options: s3.NewS3Options(),
OpenPitrixOptions: openpitrix.NewOptions(),
KubeSphereOptions: kubesphere.NewKubeSphereOptions(),
LeaderElection: &leaderelection.LeaderElectionConfig{
LeaseDuration: 30 * time.Second,
RenewDeadline: 15 * time.Second,
......@@ -47,13 +50,13 @@ func (s *KubeSphereControllerManagerOptions) ApplyTo(conf *kubesphereconfig.Conf
s.OpenPitrixOptions.ApplyTo(conf.OpenPitrixOptions)
}
func (s *KubeSphereControllerManagerOptions) Flags(o *KubeSphereControllerManagerOptions) cliflag.NamedFlagSets {
func (s *KubeSphereControllerManagerOptions) Flags() cliflag.NamedFlagSets {
fss := cliflag.NamedFlagSets{}
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), o.KubernetesOptions)
s.DevopsOptions.AddFlags(fss.FlagSet("devops"), o.DevopsOptions)
s.S3Options.AddFlags(fss.FlagSet("s3"), o.S3Options)
s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), o.OpenPitrixOptions)
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), s.KubernetesOptions)
s.DevopsOptions.AddFlags(fss.FlagSet("devops"), s.DevopsOptions)
s.S3Options.AddFlags(fss.FlagSet("s3"), s.S3Options)
s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), s.OpenPitrixOptions)
fs := fss.FlagSet("leaderelection")
s.bindLeaderElectionFlags(s.LeaderElection, fs)
......
......@@ -32,10 +32,14 @@ import (
"k8s.io/klog"
"kubesphere.io/kubesphere/cmd/controller-manager/app/options"
"kubesphere.io/kubesphere/pkg/apis"
controllerconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
"kubesphere.io/kubesphere/pkg/controller"
controllerconfig "kubesphere.io/kubesphere/pkg/server/config"
"kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/controller/namespace"
"kubesphere.io/kubesphere/pkg/controller/workspace"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
kclient "kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/utils/term"
"os"
"sigs.k8s.io/controller-runtime/pkg/manager"
......@@ -44,20 +48,20 @@ import (
func NewControllerManagerCommand() *cobra.Command {
s := options.NewKubeSphereControllerManagerOptions()
conf, err := controllerconfig.TryLoadFromDisk()
if err == nil {
s = &options.KubeSphereControllerManagerOptions{
KubernetesOptions: conf.KubernetesOptions,
DevopsOptions: conf.DevopsOptions,
S3Options: conf.S3Options,
OpenPitrixOptions: conf.OpenPitrixOptions,
}
}
cmd := &cobra.Command{
Use: "controller-manager",
Long: `KubeSphere controller manager is a daemon that`,
Run: func(cmd *cobra.Command, args []string) {
err := controllerconfig.Load()
if err != nil {
klog.Fatal(err)
os.Exit(1)
}
s = Complete(s)
if errs := s.Validate(); len(errs) != 0 {
klog.Error(utilerrors.NewAggregate(errs))
os.Exit(1)
......@@ -69,10 +73,8 @@ func NewControllerManagerCommand() *cobra.Command {
},
}
conf := loadConfFromFile()
fs := cmd.Flags()
namedFlagSets := s.Flags(conf)
namedFlagSets := s.Flags()
for _, f := range namedFlagSets.FlagSets {
fs.AddFlagSet(f)
......@@ -87,68 +89,43 @@ func NewControllerManagerCommand() *cobra.Command {
return cmd
}
func Complete(s *options.KubeSphereControllerManagerOptions) *options.KubeSphereControllerManagerOptions {
conf := controllerconfig.Get()
conf.Apply(&controllerconfig.Config{
DevopsOptions: s.DevopsOptions,
KubernetesOptions: s.KubernetesOptions,
S3Options: s.S3Options,
OpenPitrixOptions: s.OpenPitrixOptions,
})
out := &options.KubeSphereControllerManagerOptions{
KubernetesOptions: conf.KubernetesOptions,
DevopsOptions: conf.DevopsOptions,
S3Options: conf.S3Options,
OpenPitrixOptions: conf.OpenPitrixOptions,
LeaderElection: s.LeaderElection,
func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{}) error {
kubernetesClient, err := k8s.NewKubernetesClient(s.KubernetesOptions)
if err != nil {
klog.Errorf("Failed to create kubernetes clientset %v", err)
return err
}
return out
}
kubesphereClient := kclient.NewKubeSphereClient(s.KubeSphereOptions)
func CreateClientSet(conf *controllerconfig.Config, stopCh <-chan struct{}) error {
csop := &client.ClientSetOptions{}
csop.SetKubernetesOptions(conf.KubernetesOptions).
SetDevopsOptions(conf.DevopsOptions).
SetS3Options(conf.S3Options).
SetOpenPitrixOptions(conf.OpenPitrixOptions).
SetKubeSphereOptions(conf.KubeSphereOptions)
client.NewClientSetFactory(csop, stopCh)
return nil
}
func loadConfFromFile() *options.KubeSphereControllerManagerOptions {
err := controllerconfig.Load()
openpitrixClient, err := openpitrix.NewClient(s.OpenPitrixOptions)
if err != nil {
klog.Fatalf("error happened while loading config file")
klog.Errorf("Failed to create openpitrix client %v", err)
return err
}
/*
devopsClient, err := jenkins.NewDevopsClient(s.DevopsOptions)
if err != nil {
klog.Errorf("Failed to create devops client %v", err)
return err
}
conf := controllerconfig.Get()
s3Client, err := s3.NewS3Client(s.S3Options)
if err != nil {
klog.Errorf("Failed to create s3 client", err)
return err
}
return &options.KubeSphereControllerManagerOptions{
KubernetesOptions: conf.KubernetesOptions,
DevopsOptions: conf.DevopsOptions,
S3Options: conf.S3Options,
OpenPitrixOptions: conf.OpenPitrixOptions,
}
}
func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{}) error {
err := CreateClientSet(controllerconfig.Get(), stopCh)
if err != nil {
klog.Error(err)
return err
}
config := client.ClientSets().K8s().Config()
*/
informerFactory := informers.NewInformerFactories(kubernetesClient.Kubernetes(), kubernetesClient.KubeSphere(), kubernetesClient.Istio(), kubernetesClient.Application())
informerFactory.Start(stopCh)
run := func(ctx context.Context) {
klog.V(0).Info("setting up manager")
mgr, err := manager.New(config, manager.Options{})
mgr, err := manager.New(kubernetesClient.Config(), manager.Options{})
if err != nil {
klog.Fatalf("unable to set up overall controller manager: %v", err)
}
......@@ -159,16 +136,22 @@ func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{})
}
klog.V(0).Info("Setting up controllers")
if err := controller.AddToManager(mgr); err != nil {
klog.Fatalf("unable to register controllers to the manager: %v", err)
err = workspace.Add(mgr, kubesphereClient)
if err != nil {
klog.Fatal("Unable to create workspace controller")
}
err = namespace.Add(mgr, openpitrixClient)
if err != nil {
klog.Fatal("Unable to create namespace controller")
}
if err := AddControllers(mgr, config, stopCh); err != nil {
if err := AddControllers(mgr, kubernetesClient, informerFactory, stopCh); err != nil {
klog.Fatalf("unable to register controllers to the manager: %v", err)
}
klog.V(0).Info("Starting the Cmd.")
if err := mgr.Start(stopCh); err != nil {
klog.V(0).Info("Starting the controllers.")
if err = mgr.Start(stopCh); err != nil {
klog.Fatalf("unable to run the manager: %v", err)
}
......@@ -197,8 +180,8 @@ func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{})
lock, err := resourcelock.New(resourcelock.LeasesResourceLock,
"kubesphere-system",
"ks-controller-manager",
client.ClientSets().K8s().Kubernetes().CoreV1(),
client.ClientSets().K8s().Kubernetes().CoordinationV1(),
kubernetesClient.Kubernetes().CoreV1(),
kubernetesClient.Kubernetes().CoordinationV1(),
resourcelock.ResourceLockConfig{
Identity: id,
EventRecorder: record.NewBroadcaster().NewRecorder(scheme.Scheme, v1.EventSource{
......
......@@ -10,7 +10,6 @@ import (
controllermanager "kubesphere.io/kubesphere/cmd/controller-manager/app"
ksapigateway "kubesphere.io/kubesphere/cmd/ks-apigateway/app"
ksapiserver "kubesphere.io/kubesphere/cmd/ks-apiserver/app"
ksaiam "kubesphere.io/kubesphere/cmd/ks-iam/app"
"os"
)
......@@ -46,13 +45,11 @@ func commandFor(basename string, defaultCommand *cobra.Command, commands []func(
func NewHyperSphereCommand() (*cobra.Command, []func() *cobra.Command) {
apiserver := func() *cobra.Command { return ksapiserver.NewAPIServerCommand() }
controllermanager := func() *cobra.Command { return controllermanager.NewControllerManagerCommand() }
iam := func() *cobra.Command { return ksaiam.NewAPIServerCommand() }
apigateway := func() *cobra.Command { return ksapigateway.NewAPIGatewayCommand() }
commandFns := []func() *cobra.Command{
apiserver,
controllermanager,
iam,
apigateway,
}
......
......@@ -5,8 +5,6 @@ import (
"github.com/mholt/caddy/caddy/caddymain"
"github.com/mholt/caddy/caddyhttp/httpserver"
"github.com/spf13/cobra"
apiserverconfig "kubesphere.io/kubesphere/pkg/server/config"
"kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/utils/signals"
"kubesphere.io/kubesphere/pkg/apigateway"
......@@ -21,12 +19,6 @@ for proxy request to the right backend. API Gateway also proxy
Kubernetes API Server for KubeSphere authorization purpose.
`,
RunE: func(cmd *cobra.Command, args []string) error {
err := apiserverconfig.Load()
if err != nil {
return err
}
apigateway.RegisterPlugins()
return Run(signals.SetupSignalHandler())
......@@ -39,11 +31,6 @@ Kubernetes API Server for KubeSphere authorization purpose.
}
func Run(stopCh <-chan struct{}) error {
csop := &client.ClientSetOptions{}
csop.SetKubernetesOptions(apiserverconfig.Get().KubernetesOptions)
client.NewClientSetFactory(csop, stopCh)
httpserver.RegisterDevDirective("authenticate", "jwt")
httpserver.RegisterDevDirective("authentication", "jwt")
httpserver.RegisterDevDirective("swagger", "jwt")
......
package options
import (
"crypto/tls"
"flag"
"fmt"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api/iam"
"kubesphere.io/kubesphere/pkg/apiserver"
genericoptions "kubesphere.io/kubesphere/pkg/server/options"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
esclient "kubesphere.io/kubesphere/pkg/simple/client/logging/elasticsearch"
"kubesphere.io/kubesphere/pkg/simple/client/monitoring/prometheus"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
......@@ -14,6 +20,7 @@ import (
"kubesphere.io/kubesphere/pkg/simple/client/s3"
"kubesphere.io/kubesphere/pkg/simple/client/servicemesh"
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
"net/http"
"strings"
)
......@@ -29,6 +36,9 @@ type ServerRunOptions struct {
S3Options *s3.Options
OpenPitrixOptions *openpitrix.Options
LoggingOptions *esclient.Options
LdapOptions *ldap.Options
CacheOptions *cache.Options
AuthenticateOptions *iam.AuthenticationOptions
}
func NewServerRunOptions() *ServerRunOptions {
......@@ -44,22 +54,28 @@ func NewServerRunOptions() *ServerRunOptions {
S3Options: s3.NewS3Options(),
OpenPitrixOptions: openpitrix.NewOptions(),
LoggingOptions: esclient.NewElasticSearchOptions(),
LdapOptions: ldap.NewOptions(),
CacheOptions: cache.NewRedisOptions(),
AuthenticateOptions: iam.NewAuthenticateOptions(),
}
return &s
}
func (s *ServerRunOptions) Flags(c *ServerRunOptions) (fss cliflag.NamedFlagSets) {
s.GenericServerRunOptions.AddFlags(fss.FlagSet("generic"), c.GenericServerRunOptions)
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), c.KubernetesOptions)
s.MySQLOptions.AddFlags(fss.FlagSet("mysql"), c.MySQLOptions)
s.DevopsOptions.AddFlags(fss.FlagSet("devops"), c.DevopsOptions)
s.SonarQubeOptions.AddFlags(fss.FlagSet("sonarqube"), c.SonarQubeOptions)
s.S3Options.AddFlags(fss.FlagSet("s3"), c.S3Options)
s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), c.OpenPitrixOptions)
s.ServiceMeshOptions.AddFlags(fss.FlagSet("servicemesh"), c.ServiceMeshOptions)
s.MonitoringOptions.AddFlags(fss.FlagSet("monitoring"), c.MonitoringOptions)
s.LoggingOptions.AddFlags(fss.FlagSet("logging"), c.LoggingOptions)
func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) {
s.GenericServerRunOptions.AddFlags(fss.FlagSet("generic"), s.GenericServerRunOptions)
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), s.KubernetesOptions)
s.AuthenticateOptions.AddFlags(fss.FlagSet("authenticate"), s.AuthenticateOptions)
s.MySQLOptions.AddFlags(fss.FlagSet("mysql"), s.MySQLOptions)
s.DevopsOptions.AddFlags(fss.FlagSet("devops"), s.DevopsOptions)
s.SonarQubeOptions.AddFlags(fss.FlagSet("sonarqube"), s.SonarQubeOptions)
s.LdapOptions.AddFlags(fss.FlagSet("ldap"), s.LdapOptions)
s.CacheOptions.AddFlags(fss.FlagSet("cache"), s.CacheOptions)
s.S3Options.AddFlags(fss.FlagSet("s3"), s.S3Options)
s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), s.OpenPitrixOptions)
s.ServiceMeshOptions.AddFlags(fss.FlagSet("servicemesh"), s.ServiceMeshOptions)
s.MonitoringOptions.AddFlags(fss.FlagSet("monitoring"), s.MonitoringOptions)
s.LoggingOptions.AddFlags(fss.FlagSet("logging"), s.LoggingOptions)
fs := fss.FlagSet("klog")
local := flag.NewFlagSet("klog", flag.ExitOnError)
......@@ -71,3 +87,62 @@ func (s *ServerRunOptions) Flags(c *ServerRunOptions) (fss cliflag.NamedFlagSets
return fss
}
func (s *ServerRunOptions) NewAPIServer(stopCh <-chan struct{}) (*apiserver.APIServer, error) {
kubernetesClient, err := k8s.NewKubernetesClient(s.KubernetesOptions)
if err != nil {
return nil, err
}
monitoringClient := prometheus.NewPrometheus(s.MonitoringOptions)
loggingClient, err := esclient.NewElasticsearch(s.LoggingOptions)
if err != nil {
return nil, err
}
s3Client, err := s3.NewS3Client(s.S3Options)
if err != nil {
return nil, err
}
devopsClient, err := jenkins.NewDevopsClient(s.DevopsOptions)
if err != nil {
return nil, err
}
ldapClient, err := ldap.NewLdapClient(s.LdapOptions, stopCh)
if err != nil {
return nil, err
}
cacheClient, err := cache.NewRedisClient(s.CacheOptions, stopCh)
if err != nil {
return nil, err
}
server := &http.Server{
Addr: fmt.Sprintf(":%d", s.GenericServerRunOptions.InsecurePort),
}
if s.GenericServerRunOptions.SecurePort != 0 {
certificate, err := tls.LoadX509KeyPair(s.GenericServerRunOptions.TlsCertFile, s.GenericServerRunOptions.TlsPrivateKey)
if err != nil {
return nil, err
}
server.TLSConfig.Certificates = []tls.Certificate{certificate}
}
apiServer := &apiserver.APIServer{
Server: server,
KubernetesClient: kubernetesClient,
MonitoringClient: monitoringClient,
LoggingClient: loggingClient,
S3Client: s3Client,
DevopsClient: devopsClient,
LdapClient: ldapClient,
CacheClient: cacheClient,
}
return apiServer, nil
}
......@@ -5,6 +5,7 @@ package options
func (s *ServerRunOptions) Validate() []error {
var errors []error
errors = append(errors, s.GenericServerRunOptions.Validate()...)
errors = append(errors, s.DevopsOptions.Validate()...)
errors = append(errors, s.KubernetesOptions.Validate()...)
errors = append(errors, s.MySQLOptions.Validate()...)
......
......@@ -21,31 +21,35 @@ import (
"fmt"
kconfig "github.com/kiali/kiali/config"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog"
"kubesphere.io/kubesphere/cmd/ks-apiserver/app/options"
"kubesphere.io/kubesphere/pkg/apiserver"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
apiserverconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
"kubesphere.io/kubesphere/pkg/apiserver/servicemesh/tracing"
kinformers "kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/kapis"
"kubesphere.io/kubesphere/pkg/server"
apiserverconfig "kubesphere.io/kubesphere/pkg/server/config"
"kubesphere.io/kubesphere/pkg/server/filter"
"kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/simple/client/s3"
"kubesphere.io/kubesphere/pkg/utils/signals"
"kubesphere.io/kubesphere/pkg/utils/term"
"net/http"
)
func NewAPIServerCommand() *cobra.Command {
s := options.NewServerRunOptions()
// Load configuration from file
conf, err := apiserverconfig.TryLoadFromDisk()
if err == nil {
s = &options.ServerRunOptions{
KubernetesOptions: conf.KubernetesOptions,
DevopsOptions: conf.DevopsOptions,
SonarQubeOptions: conf.SonarQubeOptions,
ServiceMeshOptions: conf.ServiceMeshOptions,
MySQLOptions: conf.MySQLOptions,
MonitoringOptions: conf.MonitoringOptions,
S3Options: conf.S3Options,
OpenPitrixOptions: conf.OpenPitrixOptions,
LoggingOptions: conf.LoggingOptions,
AuthenticateOptions: conf.AuthenticateOptions,
}
}
cmd := &cobra.Command{
Use: "ks-apiserver",
Long: `The KubeSphere API server validates and configures data for the api objects.
......@@ -60,11 +64,8 @@ cluster's shared state through which all other components interact.`,
},
}
configOptions := load()
fs := cmd.Flags()
namedFlagSets := s.Flags(configOptions)
namedFlagSets := s.Flags()
for _, f := range namedFlagSets.FlagSets {
fs.AddFlagSet(f)
}
......@@ -80,24 +81,19 @@ cluster's shared state through which all other components interact.`,
func Run(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
err := CreateClientSet(apiserverconfig.Get(), stopCh)
if err != nil {
return err
}
initializeServicemeshConfig(s)
err = WaitForResourceSync(stopCh)
apiserver, err := s.NewAPIServer(stopCh)
if err != nil {
return err
}
initializeServicemeshConfig(s)
err = CreateAPIServer(s)
err = apiserver.PrepareRun()
if err != nil {
return err
return nil
}
return nil
return apiserver.Run(stopCh)
}
func initializeServicemeshConfig(s *options.ServerRunOptions) {
......@@ -119,234 +115,3 @@ func initializeServicemeshConfig(s *options.ServerRunOptions) {
kconfig.Set(config)
}
//
func CreateAPIServer(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
var err error
deps := createDeps(s, stopCh)
apiserver := apiserver.New(deps)
container := runtime.Container
container.DoNotRecover(false)
container.Filter(filter.Logging)
container.RecoverHandler(server.LogStackOnRecover)
kapis.InstallAPIs(container)
// install config api
apiserverconfig.InstallAPI(container)
if s.GenericServerRunOptions.InsecurePort != 0 {
err = http.ListenAndServe(fmt.Sprintf("%s:%d", s.GenericServerRunOptions.BindAddress, s.GenericServerRunOptions.InsecurePort), container)
if err == nil {
klog.V(0).Infof("Server listening on insecure port %d.", s.GenericServerRunOptions.InsecurePort)
}
}
if s.GenericServerRunOptions.SecurePort != 0 && len(s.GenericServerRunOptions.TlsCertFile) > 0 && len(s.GenericServerRunOptions.TlsPrivateKey) > 0 {
err = http.ListenAndServeTLS(fmt.Sprintf("%s:%d", s.GenericServerRunOptions.BindAddress, s.GenericServerRunOptions.SecurePort), s.GenericServerRunOptions.TlsCertFile, s.GenericServerRunOptions.TlsPrivateKey, container)
if err == nil {
klog.V(0).Infof("Server listening on secure port %d.", s.GenericServerRunOptions.SecurePort)
}
}
return err
}
func createDeps(s *options.ServerRunOptions, stopCh <-chan struct{}) *apiserver.Dependencies {
deps := &apiserver.Dependencies{}
if s.KubernetesOptions == nil || s.KubernetesOptions.KubeConfig == "" {
klog.Warning("kubeconfig not provided, will use in-cluster config")
}
var err error
deps.KubeClient, err = k8s.NewKubernetesClient(s.KubernetesOptions)
if err != nil {
klog.Fatalf("error happened when initializing kubernetes client, %v", err)
}
if s.S3Options != nil && s.S3Options.Endpoint != "" {
deps.S3, err = s3.NewS3Client(s.S3Options)
if err != nil {
klog.Fatalf("error initializing s3 client, %v", err)
}
}
if s.OpenPitrixOptions != nil && !s.OpenPitrixOptions.IsEmpty() {
deps.OpenPitrix, err = openpitrix.NewClient(s.OpenPitrixOptions)
if err != nil {
klog.Fatalf("error happened when initializing openpitrix client, %v", err)
}
}
return deps
}
func WaitForResourceSync(stopCh <-chan struct{}) error {
klog.V(0).Info("Start cache objects")
discoveryClient := client.ClientSets().K8s().Discovery()
apiResourcesList, err := discoveryClient.ServerResources()
if err != nil {
return err
}
isResourceExists := func(resource schema.GroupVersionResource) bool {
for _, apiResource := range apiResourcesList {
if apiResource.GroupVersion == resource.GroupVersion().String() {
for _, rsc := range apiResource.APIResources {
if rsc.Name == resource.Resource {
return true
}
}
}
}
return false
}
informerFactory := kinformers.NewInformerFactories(client.ClientSets().K8s().Kubernetes(), client.ClientSets().K8s().KubeSphere(), client.ClientSets().K8s().S2i(),
client.ClientSets().K8s().Application())
// resources we have to create informer first
k8sGVRs := []schema.GroupVersionResource{
{Group: "", Version: "v1", Resource: "namespaces"},
{Group: "", Version: "v1", Resource: "nodes"},
{Group: "", Version: "v1", Resource: "resourcequotas"},
{Group: "", Version: "v1", Resource: "pods"},
{Group: "", Version: "v1", Resource: "services"},
{Group: "", Version: "v1", Resource: "persistentvolumeclaims"},
{Group: "", Version: "v1", Resource: "secrets"},
{Group: "", Version: "v1", Resource: "configmaps"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "roles"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "rolebindings"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"},
{Group: "apps", Version: "v1", Resource: "deployments"},
{Group: "apps", Version: "v1", Resource: "daemonsets"},
{Group: "apps", Version: "v1", Resource: "replicasets"},
{Group: "apps", Version: "v1", Resource: "statefulsets"},
{Group: "apps", Version: "v1", Resource: "controllerrevisions"},
{Group: "storage.k8s.io", Version: "v1", Resource: "storageclasses"},
{Group: "batch", Version: "v1", Resource: "jobs"},
{Group: "batch", Version: "v1beta1", Resource: "cronjobs"},
{Group: "extensions", Version: "v1beta1", Resource: "ingresses"},
{Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"},
}
for _, gvr := range k8sGVRs {
if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr)
} else {
_, err := informerFactory.KubernetesSharedInformerFactory().ForResource(gvr)
if err != nil {
klog.Errorf("cannot create informer for %s", gvr)
return err
}
}
}
informerFactory.KubernetesSharedInformerFactory().Start(stopCh)
informerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(stopCh)
s2iInformerFactory := informerFactory.S2iSharedInformerFactory()
s2iGVRs := []schema.GroupVersionResource{
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2iruns"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"},
}
for _, gvr := range s2iGVRs {
if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr)
} else {
_, err := s2iInformerFactory.ForResource(gvr)
if err != nil {
return err
}
}
}
s2iInformerFactory.Start(stopCh)
s2iInformerFactory.WaitForCacheSync(stopCh)
ksInformerFactory := informerFactory.KubeSphereSharedInformerFactory()
ksGVRs := []schema.GroupVersionResource{
{Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibinaries"},
{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "strategies"},
{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "servicepolicies"},
}
for _, gvr := range ksGVRs {
if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr)
} else {
_, err := ksInformerFactory.ForResource(gvr)
if err != nil {
return err
}
}
}
ksInformerFactory.Start(stopCh)
ksInformerFactory.WaitForCacheSync(stopCh)
appInformerFactory := informerFactory.ApplicationSharedInformerFactory()
appGVRs := []schema.GroupVersionResource{
{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"},
}
for _, gvr := range appGVRs {
if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr)
} else {
_, err := appInformerFactory.ForResource(gvr)
if err != nil {
return err
}
}
}
appInformerFactory.Start(stopCh)
appInformerFactory.WaitForCacheSync(stopCh)
klog.V(0).Info("Finished caching objects")
return nil
}
// load options from config file
func load() *options.ServerRunOptions {
conf := apiserverconfig.Get()
return &options.ServerRunOptions{
KubernetesOptions: conf.KubernetesOptions,
DevopsOptions: conf.DevopsOptions,
SonarQubeOptions: conf.SonarQubeOptions,
ServiceMeshOptions: conf.ServiceMeshOptions,
MySQLOptions: conf.MySQLOptions,
MonitoringOptions: conf.MonitoringOptions,
S3Options: conf.S3Options,
OpenPitrixOptions: conf.OpenPitrixOptions,
LoggingOptions: conf.LoggingOptions,
}
}
func initConfigz() error {
return nil
}
/*
Copyright 2019 The KubeSphere 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 (
"kubesphere.io/kubesphere/cmd/ks-iam/app"
"log"
)
func main() {
cmd := app.NewAPIServerCommand()
if err := cmd.Execute(); err != nil {
log.Fatalln(err)
}
}
/*
Copyright 2019 The KubeSphere Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package options
import (
"flag"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog"
genericoptions "kubesphere.io/kubesphere/pkg/server/options"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"strings"
"time"
)
type ServerRunOptions struct {
GenericServerRunOptions *genericoptions.ServerRunOptions
KubernetesOptions *k8s.KubernetesOptions
LdapOptions *ldap.Options
RedisOptions *cache.Options
MySQLOptions *mysql.Options
AdminEmail string
AdminPassword string
TokenIdleTimeout time.Duration
JWTSecret string
AuthRateLimit string
EnableMultiLogin bool
GenerateKubeConfig bool
}
func NewServerRunOptions() *ServerRunOptions {
s := &ServerRunOptions{
GenericServerRunOptions: genericoptions.NewServerRunOptions(),
KubernetesOptions: k8s.NewKubernetesOptions(),
LdapOptions: ldap.NewOptions(),
MySQLOptions: mysql.NewMySQLOptions(),
RedisOptions: cache.NewRedisOptions(),
}
return s
}
func (s *ServerRunOptions) Flags(conf *ServerRunOptions) (fss cliflag.NamedFlagSets) {
fs := fss.FlagSet("generic")
s.GenericServerRunOptions.AddFlags(fs, conf.GenericServerRunOptions)
fs.StringVar(&s.AdminEmail, "admin-email", "admin@kubesphere.io", "default administrator's email")
fs.StringVar(&s.AdminPassword, "admin-password", "passw0rd", "default administrator's password")
fs.DurationVar(&s.TokenIdleTimeout, "token-idle-timeout", 30*time.Minute, "tokens that are idle beyond that time will expire,0s means the token has no expiration time. valid time units are \"ns\",\"us\",\"ms\",\"s\",\"m\",\"h\"")
fs.StringVar(&s.JWTSecret, "jwt-secret", "", "jwt secret")
fs.StringVar(&s.AuthRateLimit, "auth-rate-limit", "5/30m", "specifies the maximum number of authentication attempts permitted and time interval,valid time units are \"s\",\"m\",\"h\"")
fs.BoolVar(&s.EnableMultiLogin, "enable-multi-login", false, "allow one account to have multiple sessions")
fs.BoolVar(&s.GenerateKubeConfig, "generate-kubeconfig", true, "generate kubeconfig for new users, kubeconfig is required in devops pipeline, set to false if you don't need devops.")
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), conf.KubernetesOptions)
s.LdapOptions.AddFlags(fss.FlagSet("ldap"), conf.LdapOptions)
s.RedisOptions.AddFlags(fss.FlagSet("redis"), conf.RedisOptions)
s.MySQLOptions.AddFlags(fss.FlagSet("mysql"), conf.MySQLOptions)
kfs := fss.FlagSet("klog")
local := flag.NewFlagSet("klog", flag.ExitOnError)
klog.InitFlags(local)
local.VisitAll(func(fl *flag.Flag) {
fl.Name = strings.Replace(fl.Name, "_", "-", -1)
kfs.AddGoFlag(fl)
})
return fss
}
package options
func (s *ServerRunOptions) Validate() []error {
errs := []error{}
errs = append(errs, s.KubernetesOptions.Validate()...)
errs = append(errs, s.GenericServerRunOptions.Validate()...)
errs = append(errs, s.LdapOptions.Validate()...)
return errs
}
/*
Copyright 2019 The KubeSphere 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 app
import (
"fmt"
"github.com/spf13/cobra"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog"
"kubesphere.io/kubesphere/cmd/ks-iam/app/options"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/kapis"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/server"
apiserverconfig "kubesphere.io/kubesphere/pkg/server/config"
"kubesphere.io/kubesphere/pkg/server/filter"
"kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/utils/jwtutil"
"kubesphere.io/kubesphere/pkg/utils/signals"
"kubesphere.io/kubesphere/pkg/utils/term"
"net/http"
)
func NewAPIServerCommand() *cobra.Command {
s := options.NewServerRunOptions()
cmd := &cobra.Command{
Use: "ks-iam",
Long: `The KubeSphere account server validates and configures data
for the api objects. The API Server services REST operations and provides the frontend to the
cluster's shared state through which all other components interact.`,
RunE: func(cmd *cobra.Command, args []string) error {
err := apiserverconfig.Load()
if err != nil {
return err
}
if errs := s.Validate(); len(errs) != 0 {
return utilerrors.NewAggregate(errs)
}
return Run(s, signals.SetupSignalHandler())
},
}
conf := loadFromFile()
fs := cmd.Flags()
namedFlagSets := s.Flags(conf)
for _, f := range namedFlagSets.FlagSets {
fs.AddFlagSet(f)
}
usageFmt := "Usage:\n %s\n"
cols, _, _ := term.TerminalSize(cmd.OutOrStdout())
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
fmt.Fprintf(cmd.OutOrStdout(), "%s\n\n"+usageFmt, cmd.Long, cmd.UseLine())
cliflag.PrintSections(cmd.OutOrStdout(), namedFlagSets, cols)
})
return cmd
}
func Run(s *options.ServerRunOptions, stopChan <-chan struct{}) error {
csop := client.NewClientSetOptions()
csop.SetKubernetesOptions(s.KubernetesOptions).
SetLdapOptions(s.LdapOptions).
SetRedisOptions(s.RedisOptions).
SetMySQLOptions(s.MySQLOptions)
client.NewClientSetFactory(csop, stopChan)
waitForResourceSync(stopChan)
err := iam.Init(s.AdminEmail, s.AdminPassword, s.AuthRateLimit, s.TokenIdleTimeout, s.EnableMultiLogin, s.GenerateKubeConfig)
jwtutil.Setup(s.JWTSecret)
if err != nil {
return err
}
container := runtime.Container
container.Filter(filter.Logging)
container.DoNotRecover(false)
container.RecoverHandler(server.LogStackOnRecover)
kapis.InstallAuthorizationAPIs(container)
if s.GenericServerRunOptions.InsecurePort != 0 {
klog.Infof("Server listening on %s:%d ", s.GenericServerRunOptions.BindAddress, s.GenericServerRunOptions.InsecurePort)
err = http.ListenAndServe(fmt.Sprintf("%s:%d", s.GenericServerRunOptions.BindAddress, s.GenericServerRunOptions.InsecurePort), container)
}
if s.GenericServerRunOptions.SecurePort != 0 && len(s.GenericServerRunOptions.TlsCertFile) > 0 && len(s.GenericServerRunOptions.TlsPrivateKey) > 0 {
klog.Infof("Server listening on %s:%d", s.GenericServerRunOptions.BindAddress, s.GenericServerRunOptions.SecurePort)
err = http.ListenAndServeTLS(fmt.Sprintf("%s:%d", s.GenericServerRunOptions.BindAddress, s.GenericServerRunOptions.SecurePort), s.GenericServerRunOptions.TlsCertFile, s.GenericServerRunOptions.TlsPrivateKey, container)
}
return err
}
func loadFromFile() *options.ServerRunOptions {
err := apiserverconfig.Load()
if err != nil {
klog.Fatal(err)
}
conf := apiserverconfig.Get()
return &options.ServerRunOptions{
KubernetesOptions: conf.KubernetesOptions,
LdapOptions: conf.LdapOptions,
RedisOptions: conf.RedisOptions,
MySQLOptions: conf.MySQLOptions,
}
}
func waitForResourceSync(stopCh <-chan struct{}) {
informerFactory := informers.SharedInformerFactory()
informerFactory.Rbac().V1().Roles().Lister()
informerFactory.Rbac().V1().RoleBindings().Lister()
informerFactory.Rbac().V1().ClusterRoles().Lister()
informerFactory.Rbac().V1().ClusterRoleBindings().Lister()
informerFactory.Core().V1().Namespaces().Lister()
informerFactory.Start(stopCh)
informerFactory.WaitForCacheSync(stopCh)
ksInformerFactory := informers.KsSharedInformerFactory()
ksInformerFactory.Tenant().V1alpha1().Workspaces().Lister()
ksInformerFactory.Start(stopCh)
ksInformerFactory.WaitForCacheSync(stopCh)
}
此差异已折叠。
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: (devel)
creationTimestamp: null
name: s2ibuildertemplates.devops.kubesphere.io
spec:
additionalPrinterColumns:
- JSONPath: .spec.codeFramework
name: Framework
type: string
- JSONPath: .spec.defaultBaseImage
name: DefaultBaseImage
type: string
- JSONPath: .spec.version
name: Version
type: string
group: devops.kubesphere.io
names:
categories:
- devops
kind: S2iBuilderTemplate
listKind: S2iBuilderTemplateList
plural: s2ibuildertemplates
shortNames:
- s2ibt
singular: s2ibuildertemplate
scope: Cluster
subresources: {}
validation:
openAPIV3Schema:
description: S2iBuilderTemplate is the Schema for the s2ibuildertemplates API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: S2iBuilderTemplateSpec defines the desired state of S2iBuilderTemplate
properties:
codeFramework:
description: CodeFramework means which language this template is designed
for and which framework is using if has framework. Like Java, NodeJS
etc
type: string
containerInfo:
description: Images are the images this template will use.
items:
properties:
buildVolumes:
description: BuildVolumes specifies a list of volumes to mount
to container running the build.
items:
type: string
type: array
builderImage:
description: BaseImage are the images this template will use.
type: string
runtimeArtifacts:
items:
description: VolumeSpec represents a single volume mount point.
properties:
destination:
description: Destination is the path to mount the volume
to - absolute or relative.
type: string
keep:
description: Keep indicates if the mounted data should be
kept in the final image.
type: boolean
source:
description: Source is a reference to the volume source.
type: string
type: object
type: array
runtimeImage:
type: string
type: object
type: array
defaultBaseImage:
description: DefaultBaseImage is the image that will be used by default
type: string
description:
description: Description illustrate the purpose of this template
type: string
environment:
description: Parameters is a set of environment variables to be passed
to the image.
items:
properties:
defaultValue:
type: string
description:
type: string
key:
type: string
optValues:
items:
type: string
type: array
required:
type: boolean
type:
type: string
value:
type: string
type: object
type: array
iconPath:
description: IconPath is used for frontend display
type: string
version:
description: Version of template
type: string
type: object
status:
description: S2iBuilderTemplateStatus defines the observed state of S2iBuilderTemplate
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: (devel)
creationTimestamp: null
name: s2iruns.devops.kubesphere.io
spec:
additionalPrinterColumns:
- JSONPath: .status.runState
name: State
type: string
- JSONPath: .status.kubernetesJobName
name: K8sJobName
type: string
- JSONPath: .status.startTime
name: StartTime
type: date
- JSONPath: .status.completionTime
name: CompletionTime
type: date
- JSONPath: .status.s2iBuildResult.imageName
name: ImageName
type: string
group: devops.kubesphere.io
names:
kind: S2iRun
listKind: S2iRunList
plural: s2iruns
shortNames:
- s2ir
singular: s2irun
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: S2iRun is the Schema for the s2iruns API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: S2iRunSpec defines the desired state of S2iRun
properties:
backoffLimit:
description: BackoffLimit limits the restart count of each s2irun. Default
is 0
format: int32
type: integer
builderName:
description: BuilderName specify the name of s2ibuilder, required
type: string
newRevisionId:
description: NewRevisionId override the default NewRevisionId in its
s2ibuilder.
type: string
newSourceURL:
description: NewSourceURL is used to download new binary artifacts
type: string
newTag:
description: NewTag override the default tag in its s2ibuilder, image
name cannot be changed.
type: string
secondsAfterFinished:
description: SecondsAfterFinished if is set and greater than zero, and
the job created by s2irun become successful or failed , the job will
be auto deleted after SecondsAfterFinished
format: int32
type: integer
required:
- builderName
type: object
status:
description: S2iRunStatus defines the observed state of S2iRun
properties:
completionTime:
description: Represents time when the job was completed. It is not guaranteed
to be set in happens-before order across separate operations. It is
represented in RFC3339 form and is in UTC.
format: date-time
type: string
kubernetesJobName:
description: KubernetesJobName is the job name in k8s
type: string
logURL:
description: LogURL is uesd for external log handler to let user know
where is log located in
type: string
runState:
description: RunState indicates whether this job is done or failed
type: string
s2iBuildResult:
description: S2i build result info.
properties:
commandPull:
description: Command for pull image.
type: string
imageCreated:
description: Image created time.
type: string
imageID:
description: Image ID.
type: string
imageName:
description: ImageName is the name of artifact
type: string
imageRepoTags:
description: image tags.
items:
type: string
type: array
imageSize:
description: The size in bytes of the image
format: int64
type: integer
type: object
s2iBuildSource:
description: S2i build source info.
properties:
binaryName:
description: Binary file Name
type: string
binarySize:
description: Binary file Size
format: int64
type: integer
builderImage:
description: // BuilderImage describes which image is used for building
the result images.
type: string
commitID:
description: CommitID represents an arbitrary extended object reference
in Git as SHA-1
type: string
committerEmail:
description: CommitterEmail contains the e-mail of the committer
type: string
committerName:
description: CommitterName contains the name of the committer
type: string
description:
description: Description is a result image description label. The
default is no description.
type: string
revisionId:
description: The RevisionId is a branch name or a SHA-1 hash of
every important thing about the commit
type: string
sourceUrl:
description: SourceURL is url of the codes such as https://github.com/a/b.git
type: string
type: object
startTime:
description: StartTime represent when this run began
format: date-time
type: string
type: object
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
......@@ -32,6 +32,8 @@ require (
github.com/fatih/structs v1.1.0
github.com/go-ldap/ldap v3.0.3+incompatible
github.com/go-logr/logr v0.1.0
github.com/go-logr/zapr v0.1.1 // indirect
github.com/go-openapi/jsonreference v0.19.3 // indirect
github.com/go-openapi/spec v0.19.3
github.com/go-openapi/strfmt v0.19.0
github.com/go-playground/universal-translator v0.16.0 // indirect
......@@ -55,11 +57,11 @@ require (
github.com/klauspost/cpuid v1.2.1 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/kubernetes-sigs/application v0.0.0-20191210100950-18cc93526ab4
github.com/kubesphere/s2ioperator v0.0.14
github.com/kubesphere/sonargo v0.0.2
github.com/leodido/go-urn v1.1.0 // indirect
github.com/lib/pq v1.2.0 // indirect
github.com/lucas-clemente/quic-go v0.11.1 // indirect
github.com/mailru/easyjson v0.7.0 // indirect
github.com/mattn/go-sqlite3 v1.11.0 // indirect
github.com/mholt/caddy v1.0.0
github.com/mholt/certmagic v0.5.1 // indirect
......@@ -82,6 +84,7 @@ require (
github.com/xanzy/ssh-agent v0.2.1 // indirect
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 // indirect
google.golang.org/grpc v1.23.1
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d // indirect
gopkg.in/go-playground/validator.v9 v9.29.1 // indirect
......@@ -98,6 +101,7 @@ require (
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33
k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894
k8s.io/component-base v0.0.0-20191114102325-35a9586014f7
k8s.io/gengo v0.0.0-20191120174120-e74f70b9b27e // indirect
k8s.io/klog v1.0.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f // indirect
......
......@@ -16,7 +16,6 @@ fi
docker build -f build/ks-apigateway/Dockerfile -t $REPO/ks-apigateway:$TAG .
docker build -f build/ks-apiserver/Dockerfile -t $REPO/ks-apiserver:$TAG .
docker build -f build/ks-iam/Dockerfile -t $REPO/ks-account:$TAG .
docker build -f build/ks-controller-manager/Dockerfile -t $REPO/ks-controller-manager:$TAG .
docker build -f build/hypersphere/Dockerfile -t $REPO/hypersphere:$TAG .
docker build -f ./pkg/db/Dockerfile -t $REPO/ks-devops:flyway-$TAG ./pkg/db/
......@@ -26,7 +25,6 @@ docker build -f ./pkg/db/Dockerfile -t $REPO/ks-devops:flyway-$TAG ./pkg/db/
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker push $REPO/ks-apigateway:$TAG
docker push $REPO/ks-apiserver:$TAG
docker push $REPO/ks-account:$TAG
docker push $REPO/ks-controller-manager:$TAG
docker push $REPO/hypersphere:$TAG
docker push $REPO/ks-devops:flyway-$TAG
package iam
import (
"github.com/spf13/pflag"
"time"
)
type AuthenticationOptions struct {
// authenticate rate limit will
AuthenticateRateLimiterMaxTries int
AuthenticateRateLimiterDuration time.Duration
// maximum retries when authenticate failed
MaxAuthenticateRetries int
// token validation duration, will refresh token expiration for each user request
TokenExpiration time.Duration
// allow multiple users login at the same time
MultipleLogin bool
}
func NewAuthenticateOptions() *AuthenticationOptions {
return &AuthenticationOptions{
AuthenticateRateLimiterMaxTries: 5,
AuthenticateRateLimiterDuration: time.Minute * 30,
MaxAuthenticateRetries: 0,
TokenExpiration: 0,
MultipleLogin: false,
}
}
func (options *AuthenticationOptions) Validate() []error {
var errs []error
return errs
}
func (options *AuthenticationOptions) AddFlags(fs *pflag.FlagSet, s *AuthenticationOptions) {
fs.IntVar(&options.AuthenticateRateLimiterMaxTries, "authenticate-rate-limiter-max-retries", s.AuthenticateRateLimiterMaxTries, "")
fs.DurationVar(&options.AuthenticateRateLimiterDuration, "authenticate-rate-limiter-duration", s.AuthenticateRateLimiterDuration, "")
fs.IntVar(&options.MaxAuthenticateRetries, "authenticate-max-retries", s.MaxAuthenticateRetries, "")
fs.DurationVar(&options.TokenExpiration, "token-expiration", s.TokenExpiration, "")
fs.BoolVar(&options.MultipleLogin, "multiple-login", s.MultipleLogin, "")
}
/*
*
* Copyright 2020 The KubeSphere 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 iam
import (
"kubesphere.io/kubesphere/pkg/server/errors"
"time"
)
const (
KindTokenReview = "TokenReview"
)
type User struct {
Username string `json:"username"`
Email string `json:"email"`
......@@ -35,3 +14,27 @@ type User struct {
Groups []string `json:"groups,omitempty"`
Password string `json:"password,omitempty"`
}
func NewUser() *User {
return &User{
Username: "",
Email: "",
Lang: "",
Description: "",
CreateTime: time.Time{},
Groups: nil,
Password: "",
}
}
func (u *User) Validate() error {
if u.Username == "" {
return errors.New("username can not be empty")
}
if u.Password == "" {
return errors.New("password can not be empty")
}
return nil
}
......@@ -20,7 +20,7 @@ package v1alpha2
import (
"fmt"
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/api/iam"
"net/mail"
)
......
......@@ -21,9 +21,9 @@ import (
)
const (
ResourceKindS2iBinary = "S2iBinary"
ResourceSingularServicePolicy = "s2ibinary"
ResourcePluralServicePolicy = "s2ibinaries"
ResourceKindS2iBinary = "S2iBinary"
ResourceSingularS2iBinary = "s2ibinary"
ResourcePluralS2iBinary = "s2ibinaries"
)
const (
......
......@@ -422,6 +422,12 @@ type S2iConfig struct {
// Whether output build result to status.
OutputBuildResult bool `json:"outputBuildResult,omitempty"`
// Regular expressions, ignoring names that do not match the provided regular expression
BranchExpression string `json:"branchExpression,omitempty"`
// SecretCode
SecretCode string `json:"secretCode,omitempty"`
}
type UserDefineTemplate struct {
......
......@@ -13,12 +13,46 @@ 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.
*/
// Code generated by client-gen. DO NOT EDIT.
package v1alpha1
type S2iBuilderExpansion interface{}
import (
"testing"
type S2iBuilderTemplateExpansion interface{}
"github.com/onsi/gomega"
"golang.org/x/net/context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
type S2iRunExpansion interface{}
func TestStorageS2iBuilder(t *testing.T) {
key := types.NamespacedName{
Name: "foo",
Namespace: "default",
}
created := &S2iBuilder{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
}}
g := gomega.NewGomegaWithT(t)
// Test Create
fetched := &S2iBuilder{}
g.Expect(c.Create(context.TODO(), created)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched).To(gomega.Equal(created))
// Test Updating the Labels
updated := fetched.DeepCopy()
updated.Labels = map[string]string{"hello": "world"}
g.Expect(c.Update(context.TODO(), updated)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched).To(gomega.Equal(updated))
// Test Delete
g.Expect(c.Delete(context.TODO(), fetched)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.HaveOccurred())
}
......@@ -36,6 +36,17 @@ type Parameter struct {
Value string `json:"value,omitempty"`
}
type CodeFramework string
const (
Ruby CodeFramework = "ruby"
Go CodeFramework = "go"
Java CodeFramework = "Java"
JavaTomcat CodeFramework = "JavaTomcat"
Nodejs CodeFramework = "Nodejs"
Python CodeFramework = "python"
)
func (p *Parameter) ToEnvonment() *EnvironmentSpec {
var v string
if p.Value == "" && p.DefaultValue != "" {
......
......@@ -14,33 +14,43 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
// NOTE: Boilerplate only. Ignore this file.
// Package v1alpha1 contains API Schema definitions for the devops v1alpha1 API group
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=github.com/kubesphere/s2ioperator/pkg/apis/devops
// +k8s:defaulter-gen=TypeMeta
// +groupName=devops.kubesphere.io
package v1alpha1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/runtime/scheme"
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: "devops.kubesphere.io", Version: "v1alpha1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
"testing"
// AddToScheme is required by pkg/client/...
AddToScheme = SchemeBuilder.AddToScheme
"github.com/onsi/gomega"
"golang.org/x/net/context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
// Resource is required by pkg/client/listers/...
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
func TestStorageS2iBuilderTemplate(t *testing.T) {
key := types.NamespacedName{
Name: "foo",
}
created := &S2iBuilderTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
}}
g := gomega.NewGomegaWithT(t)
// Test Create
fetched := &S2iBuilderTemplate{}
g.Expect(c.Create(context.TODO(), created)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched).To(gomega.Equal(created))
// Test Updating the Labels
updated := fetched.DeepCopy()
updated.Labels = map[string]string{"hello": "world"}
g.Expect(c.Update(context.TODO(), updated)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched).To(gomega.Equal(updated))
// Test Delete
g.Expect(c.Delete(context.TODO(), fetched)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.HaveOccurred())
}
......@@ -13,26 +13,46 @@ 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.
*/
// Code generated by lister-gen. DO NOT EDIT.
package v1alpha1
// S2iBuilderListerExpansion allows custom methods to be added to
// S2iBuilderLister.
type S2iBuilderListerExpansion interface{}
// S2iBuilderNamespaceListerExpansion allows custom methods to be added to
// S2iBuilderNamespaceLister.
type S2iBuilderNamespaceListerExpansion interface{}
// S2iBuilderTemplateListerExpansion allows custom methods to be added to
// S2iBuilderTemplateLister.
type S2iBuilderTemplateListerExpansion interface{}
// S2iRunListerExpansion allows custom methods to be added to
// S2iRunLister.
type S2iRunListerExpansion interface{}
// S2iRunNamespaceListerExpansion allows custom methods to be added to
// S2iRunNamespaceLister.
type S2iRunNamespaceListerExpansion interface{}
import (
"testing"
"github.com/onsi/gomega"
"golang.org/x/net/context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
func TestStorageS2iRun(t *testing.T) {
key := types.NamespacedName{
Name: "foo",
Namespace: "default",
}
created := &S2iRun{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
}}
g := gomega.NewGomegaWithT(t)
// Test Create
fetched := &S2iRun{}
g.Expect(c.Create(context.TODO(), created)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched).To(gomega.Equal(created))
// Test Updating the Labels
updated := fetched.DeepCopy()
updated.Labels = map[string]string{"hello": "world"}
g.Expect(c.Update(context.TODO(), updated)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched).To(gomega.Equal(updated))
// Test Delete
g.Expect(c.Delete(context.TODO(), fetched)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.HaveOccurred())
}
package apiserver
import (
"bytes"
"context"
"fmt"
"github.com/emicklei/go-restful"
"k8s.io/apimachinery/pkg/runtime/schema"
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api/iam"
"kubesphere.io/kubesphere/pkg/informers"
iamv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/iam/v1alpha2"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/logging/v1alpha2"
monitoringv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/monitoring/v1alpha2"
openpitrixv1 "kubesphere.io/kubesphere/pkg/kapis/openpitrix/v1"
operationsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/operations/v1alpha2"
resourcesv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha2"
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/server/options"
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/simple/client/db"
"kubesphere.io/kubesphere/pkg/simple/client/devops"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
"kubesphere.io/kubesphere/pkg/simple/client/logging"
"kubesphere.io/kubesphere/pkg/simple/client/monitoring"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/simple/client/s3"
"net"
"net/http"
rt "runtime"
"strings"
"time"
)
const (
......@@ -26,56 +46,295 @@ const (
MimeJsonPatchJson = "application/json-patch+json"
)
// Dependencies is objects constructed at runtime that are necessary for running apiserver.
type Dependencies struct {
// Injected Dependencies
KubeClient k8s.Client
S3 s3.Interface
OpenPitrix openpitrix.Client
Monitoring monitoring.Interface
Logging logging.Interface
Devops devops.Interface
DB db.Interface
}
type APIServer struct {
// number of kubesphere apiserver
apiserverCount int
ServerCount int
//
genericServerOptions *options.ServerRunOptions
Server *http.Server
AuthenticateOptions *iam.AuthenticationOptions
// webservice container, where all webservice defines
container *restful.Container
// kubeClient is a collection of all kubernetes(include CRDs) objects clientset
kubeClient k8s.Client
KubernetesClient k8s.Client
// informerFactory is a collection of all kubernetes(include CRDs) objects informers,
// mainly for fast query
informerFactory informers.InformerFactory
InformerFactory informers.InformerFactory
// cache is used for short lived objects, like session
cache cache.Interface
CacheClient cache.Interface
// monitoring client set
MonitoringClient monitoring.Interface
//
OpenpitrixClient openpitrix.Client
//
LoggingClient logging.Interface
//
DevopsClient devops.Interface
//
S3Client s3.Interface
//
DBClient db.Interface
//
LdapClient ldap.Interface
//
}
func (s *APIServer) PrepareRun() error {
s.container = restful.NewContainer()
s.container.Filter(logRequestAndResponse)
s.container.Router(restful.CurlyRouter{})
s.container.RecoverHandler(func(panicReason interface{}, httpWriter http.ResponseWriter) {
logStackOnRecover(panicReason, httpWriter)
})
s.installKubeSphereAPIs()
return nil
}
func (s *APIServer) installKubeSphereAPIs() {
urlruntime.Must(resourcev1alpha3.AddToContainer(s.container, s.InformerFactory))
urlruntime.Must(servicemeshv1alpha2.AddToContainer(s.container))
// Need to refactor devops api registration, too much dependencies
//urlruntime.Must(devopsv1alpha2.AddToContainer(s.container, s.DevopsClient))
urlruntime.Must(loggingv1alpha2.AddToContainer(s.container, s.KubernetesClient, s.LoggingClient))
urlruntime.Must(monitoringv1alpha2.AddToContainer(s.container, s.KubernetesClient, s.MonitoringClient))
urlruntime.Must(openpitrixv1.AddToContainer(s.container, s.InformerFactory, s.OpenpitrixClient))
urlruntime.Must(operationsv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes()))
urlruntime.Must(resourcesv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.InformerFactory))
//urlruntime.Must(tenantv1alpha2.AddToContainer(s.container, s.KubernetesClient, s.InformerFactory, s.DBClient))
urlruntime.Must(terminalv1alpha2.AddToContainer(s.container, s.KubernetesClient.Kubernetes(), s.KubernetesClient.Config()))
urlruntime.Must(iamv1alpha2.AddToContainer(s.container, s.KubernetesClient, s.InformerFactory, s.LdapClient, s.CacheClient, s.AuthenticateOptions))
}
func (s *APIServer) Run(stopCh <-chan struct{}) error {
err := s.waitForResourceSync(stopCh)
if err != nil {
return err
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
go func() {
<-stopCh
_ = s.Server.Shutdown(ctx)
}()
if s.Server.TLSConfig != nil {
return s.Server.ListenAndServeTLS("", "")
} else {
return s.Server.ListenAndServe()
}
}
func New(deps *Dependencies) *APIServer {
func (s *APIServer) waitForResourceSync(stopCh <-chan struct{}) error {
klog.V(0).Info("Start cache objects")
discoveryClient := s.KubernetesClient.Kubernetes().Discovery()
apiResourcesList, err := discoveryClient.ServerResources()
if err != nil {
return err
}
isResourceExists := func(resource schema.GroupVersionResource) bool {
for _, apiResource := range apiResourcesList {
if apiResource.GroupVersion == resource.GroupVersion().String() {
for _, rsc := range apiResource.APIResources {
if rsc.Name == resource.Resource {
return true
}
}
}
}
return false
}
// resources we have to create informer first
k8sGVRs := []schema.GroupVersionResource{
{Group: "", Version: "v1", Resource: "namespaces"},
{Group: "", Version: "v1", Resource: "nodes"},
{Group: "", Version: "v1", Resource: "resourcequotas"},
{Group: "", Version: "v1", Resource: "pods"},
{Group: "", Version: "v1", Resource: "services"},
{Group: "", Version: "v1", Resource: "persistentvolumeclaims"},
{Group: "", Version: "v1", Resource: "secrets"},
{Group: "", Version: "v1", Resource: "configmaps"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "roles"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "rolebindings"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterroles"},
{Group: "rbac.authorization.k8s.io", Version: "v1", Resource: "clusterrolebindings"},
{Group: "apps", Version: "v1", Resource: "deployments"},
{Group: "apps", Version: "v1", Resource: "daemonsets"},
{Group: "apps", Version: "v1", Resource: "replicasets"},
{Group: "apps", Version: "v1", Resource: "statefulsets"},
{Group: "apps", Version: "v1", Resource: "controllerrevisions"},
{Group: "storage.k8s.io", Version: "v1", Resource: "storageclasses"},
{Group: "batch", Version: "v1", Resource: "jobs"},
{Group: "batch", Version: "v1beta1", Resource: "cronjobs"},
{Group: "extensions", Version: "v1beta1", Resource: "ingresses"},
{Group: "autoscaling", Version: "v2beta2", Resource: "horizontalpodautoscalers"},
}
for _, gvr := range k8sGVRs {
if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr)
} else {
_, err := s.InformerFactory.KubernetesSharedInformerFactory().ForResource(gvr)
if err != nil {
klog.Errorf("cannot create informer for %s", gvr)
return err
}
}
}
s.InformerFactory.KubernetesSharedInformerFactory().Start(stopCh)
s.InformerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(stopCh)
ksInformerFactory := s.InformerFactory.KubeSphereSharedInformerFactory()
ksGVRs := []schema.GroupVersionResource{
{Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"},
}
devopsGVRs := []schema.GroupVersionResource{
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibinaries"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2iruns"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"},
}
servicemeshGVRs := []schema.GroupVersionResource{
{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "strategies"},
{Group: "servicemesh.kubesphere.io", Version: "v1alpha2", Resource: "servicepolicies"},
}
server := &APIServer{}
// skip caching devops resources if devops not enabled
if s.DevopsClient != nil {
ksGVRs = append(ksGVRs, devopsGVRs...)
}
// skip caching servicemesh resources if servicemesh not enabled
if s.KubernetesClient.Istio() != nil {
ksGVRs = append(ksGVRs, servicemeshGVRs...)
}
for _, gvr := range ksGVRs {
if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr)
} else {
_, err := ksInformerFactory.ForResource(gvr)
if err != nil {
return err
}
}
}
ksInformerFactory.Start(stopCh)
ksInformerFactory.WaitForCacheSync(stopCh)
appInformerFactory := s.InformerFactory.ApplicationSharedInformerFactory()
appGVRs := []schema.GroupVersionResource{
{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"},
}
for _, gvr := range appGVRs {
if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr)
} else {
_, err := appInformerFactory.ForResource(gvr)
if err != nil {
return err
}
}
}
appInformerFactory.Start(stopCh)
appInformerFactory.WaitForCacheSync(stopCh)
klog.V(0).Info("Finished caching objects")
return nil
return server
}
func (s *APIServer) InstallKubeSphereAPIs() {
func logStackOnRecover(panicReason interface{}, w http.ResponseWriter) {
var buffer bytes.Buffer
buffer.WriteString(fmt.Sprintf("recover from panic situation: - %v\r\n", panicReason))
for i := 2; ; i += 1 {
_, file, line, ok := rt.Caller(i)
if !ok {
break
}
buffer.WriteString(fmt.Sprintf(" %s:%d\r\n", file, line))
}
klog.Errorln(buffer.String())
headers := http.Header{}
if ct := w.Header().Get("Content-Type"); len(ct) > 0 {
headers.Set("Accept", ct)
}
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("Internal server error"))
}
resourcev1alpha3.AddWebService(s.container, s.kubeClient)
func logRequestAndResponse(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
start := time.Now()
chain.ProcessFilter(req, resp)
klog.V(4).Infof("%s - \"%s %s %s\" %d %d %dms",
getRequestIP(req),
req.Request.Method,
req.Request.RequestURI,
req.Request.Proto,
resp.StatusCode(),
resp.ContentLength(),
time.Since(start)/time.Millisecond,
)
}
func (s *APIServer) Serve() error {
panic("implement me")
func getRequestIP(req *restful.Request) string {
address := strings.Trim(req.Request.Header.Get("X-Real-Ip"), " ")
if address != "" {
return address
}
address = strings.Trim(req.Request.Header.Get("X-Forwarded-For"), " ")
if address != "" {
return address
}
address, _, err := net.SplitHostPort(req.Request.RemoteAddr)
if err != nil {
return req.Request.RemoteAddr
}
return address
}
......@@ -4,6 +4,7 @@ import (
"fmt"
"gopkg.in/yaml.v2"
"io/ioutil"
iamapi "kubesphere.io/kubesphere/pkg/api/iam"
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
"kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
......@@ -102,6 +103,13 @@ func newTestConfig() *Config {
NotificationOptions: &notification.Options{
Endpoint: "http://notification.kubesphere-alerting-system.svc:9200",
},
AuthenticateOptions: &iamapi.AuthenticationOptions{
AuthenticateRateLimiterMaxTries: 5,
AuthenticateRateLimiterDuration: 30 * time.Minute,
MaxAuthenticateRetries: 6,
TokenExpiration: 30 * time.Minute,
MultipleLogin: false,
},
}
return conf
}
......@@ -112,14 +120,14 @@ func saveTestConfig(t *testing.T, conf *Config) {
t.Fatalf("error marshal config. %v", err)
}
err = ioutil.WriteFile(fmt.Sprintf("%s.yaml", DefaultConfigurationName), content, 0640)
err = ioutil.WriteFile(fmt.Sprintf("%s.yaml", defaultConfigurationName), content, 0640)
if err != nil {
t.Fatalf("error write configuration file, %v", err)
}
}
func cleanTestConfig(t *testing.T) {
file := fmt.Sprintf("%s.yaml", DefaultConfigurationName)
file := fmt.Sprintf("%s.yaml", defaultConfigurationName)
if _, err := os.Stat(file); os.IsNotExist(err) {
t.Log("file not exists, skipping")
return
......@@ -137,11 +145,10 @@ func TestGet(t *testing.T) {
saveTestConfig(t, conf)
defer cleanTestConfig(t)
err := Load()
conf2, err := TryLoadFromDisk()
if err != nil {
t.Fatal(err)
}
conf2 := Get()
if diff := reflectutils.Equal(conf, conf2); diff != nil {
t.Fatal(diff)
......@@ -157,11 +164,10 @@ func TestKubeSphereOptions(t *testing.T) {
saveTestConfig(t, &savedConf)
defer cleanTestConfig(t)
err := Load()
loadedConf, err := TryLoadFromDisk()
if err != nil {
t.Fatal(err)
}
loadedConf := Get()
if diff := reflectutils.Equal(conf, loadedConf); diff != nil {
t.Fatal(diff)
......@@ -176,11 +182,10 @@ func TestKubeSphereOptions(t *testing.T) {
saveTestConfig(t, &savedConf)
defer cleanTestConfig(t)
err := Load()
loadedConf, err := TryLoadFromDisk()
if err != nil {
t.Fatal(err)
}
loadedConf := Get()
savedConf.KubeSphereOptions.AccountServer = "http://ks-account.kubesphere-system.svc"
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册