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.
This commit is contained in:
@@ -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)
|
||||
|
||||
6
Makefile
6
Makefile
@@ -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
|
||||
func AddControllers(
|
||||
mgr manager.Manager,
|
||||
client k8s.Client,
|
||||
informerFactory informers.InformerFactory,
|
||||
stopCh <-chan struct{}) error {
|
||||
|
||||
var log = logf.Log.WithName("controller-manager")
|
||||
kubernetesInformer := informerFactory.KubernetesSharedInformerFactory()
|
||||
istioInformer := informerFactory.IstioSharedInformerFactory()
|
||||
kubesphereInformer := informerFactory.KubeSphereSharedInformerFactory()
|
||||
applicationInformer := informerFactory.ApplicationSharedInformerFactory()
|
||||
|
||||
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)
|
||||
|
||||
kubesphereInformer := kubesphereinformers.NewSharedInformerFactory(kubesphereclient, defaultResync)
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
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()
|
||||
if err != nil {
|
||||
klog.Fatalf("error happened while loading config file")
|
||||
}
|
||||
|
||||
conf := controllerconfig.Get()
|
||||
|
||||
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)
|
||||
kubernetesClient, err := k8s.NewKubernetesClient(s.KubernetesOptions)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
klog.Errorf("Failed to create kubernetes clientset %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
config := client.ClientSets().K8s().Config()
|
||||
kubesphereClient := kclient.NewKubeSphereClient(s.KubeSphereOptions)
|
||||
|
||||
openpitrixClient, err := openpitrix.NewClient(s.OpenPitrixOptions)
|
||||
if err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
s3Client, err := s3.NewS3Client(s.S3Options)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to create s3 client", err)
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
|
||||
*/
|
||||
|
||||
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 {
|
||||
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, kubernetesClient, informerFactory, stopCh); err != nil {
|
||||
klog.Fatalf("unable to register controllers to the manager: %v", err)
|
||||
}
|
||||
|
||||
if err := AddControllers(mgr, config, 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")
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
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
|
||||
}
|
||||
|
||||
err = WaitForResourceSync(stopCh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
initializeServicemeshConfig(s)
|
||||
|
||||
err = CreateAPIServer(s)
|
||||
apiserver, err := s.NewAPIServer(stopCh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
err = apiserver.PrepareRun()
|
||||
if err != 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
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
/*
|
||||
|
||||
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
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,156 +0,0 @@
|
||||
/*
|
||||
|
||||
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)
|
||||
}
|
||||
578
config/crds/devops.kubesphere.io_s2ibuilders.yaml
generated
Normal file
578
config/crds/devops.kubesphere.io_s2ibuilders.yaml
generated
Normal file
@@ -0,0 +1,578 @@
|
||||
|
||||
---
|
||||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
controller-gen.kubebuilder.io/version: (devel)
|
||||
creationTimestamp: null
|
||||
name: s2ibuilders.devops.kubesphere.io
|
||||
spec:
|
||||
additionalPrinterColumns:
|
||||
- JSONPath: .status.runCount
|
||||
name: RunCount
|
||||
type: integer
|
||||
- JSONPath: .status.lastRunState
|
||||
name: LastRunState
|
||||
type: string
|
||||
- JSONPath: .status.lastRunName
|
||||
name: LastRunName
|
||||
type: string
|
||||
- JSONPath: .status.lastRunStartTime
|
||||
name: LastRunStartTime
|
||||
type: date
|
||||
group: devops.kubesphere.io
|
||||
names:
|
||||
kind: S2iBuilder
|
||||
listKind: S2iBuilderList
|
||||
plural: s2ibuilders
|
||||
shortNames:
|
||||
- s2ib
|
||||
singular: s2ibuilder
|
||||
scope: Namespaced
|
||||
subresources:
|
||||
status: {}
|
||||
validation:
|
||||
openAPIV3Schema:
|
||||
description: S2iBuilder is the Schema for the s2ibuilders 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: S2iBuilderSpec defines the desired state of S2iBuilder
|
||||
properties:
|
||||
config:
|
||||
description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
|
||||
Important: Run "make" to regenerate code after modifying this file'
|
||||
properties:
|
||||
addHost:
|
||||
description: AddHost Add a line to /etc/hosts for test purpose or
|
||||
private use in LAN. Its format is host:IP,muliple hosts can be
|
||||
added by using multiple --add-host
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
asDockerfile:
|
||||
description: AsDockerfile indicates the path where the Dockerfile
|
||||
should be written instead of building a new image.
|
||||
type: string
|
||||
assembleUser:
|
||||
description: AssembleUser specifies the user to run the assemble
|
||||
script in container
|
||||
type: string
|
||||
blockOnBuild:
|
||||
description: BlockOnBuild prevents s2i from performing a docker
|
||||
build operation if one is necessary to execute ONBUILD commands,
|
||||
or to layer source code into the container for images that don't
|
||||
have a tar binary available, if the image contains ONBUILD commands
|
||||
that would be executed.
|
||||
type: boolean
|
||||
branchExpression:
|
||||
description: Regular expressions, ignoring names that do not match
|
||||
the provided regular expression
|
||||
type: string
|
||||
buildVolumes:
|
||||
description: BuildVolumes specifies a list of volumes to mount to
|
||||
container running the build.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
builderBaseImageVersion:
|
||||
description: BuilderBaseImageVersion provides optional version information
|
||||
about the builder base image.
|
||||
type: string
|
||||
builderImage:
|
||||
description: BuilderImage describes which image is used for building
|
||||
the result images.
|
||||
type: string
|
||||
builderImageVersion:
|
||||
description: BuilderImageVersion provides optional version information
|
||||
about the builder image.
|
||||
type: string
|
||||
builderPullPolicy:
|
||||
description: BuilderPullPolicy specifies when to pull the builder
|
||||
image
|
||||
type: string
|
||||
callbackUrl:
|
||||
description: CallbackURL is a URL which is called upon successful
|
||||
build to inform about that fact.
|
||||
type: string
|
||||
cgroupLimits:
|
||||
description: CGroupLimits describes the cgroups limits that will
|
||||
be applied to any containers run by s2i.
|
||||
properties:
|
||||
cpuPeriod:
|
||||
format: int64
|
||||
type: integer
|
||||
cpuQuota:
|
||||
format: int64
|
||||
type: integer
|
||||
cpuShares:
|
||||
format: int64
|
||||
type: integer
|
||||
memoryLimitBytes:
|
||||
format: int64
|
||||
type: integer
|
||||
memorySwap:
|
||||
format: int64
|
||||
type: integer
|
||||
parent:
|
||||
type: string
|
||||
required:
|
||||
- cpuPeriod
|
||||
- cpuQuota
|
||||
- cpuShares
|
||||
- memoryLimitBytes
|
||||
- memorySwap
|
||||
- parent
|
||||
type: object
|
||||
contextDir:
|
||||
description: Specify a relative directory inside the application
|
||||
repository that should be used as a root directory for the application.
|
||||
type: string
|
||||
description:
|
||||
description: Description is a result image description label. The
|
||||
default is no description.
|
||||
type: string
|
||||
destination:
|
||||
description: Destination specifies a location where the untar operation
|
||||
will place its artifacts.
|
||||
type: string
|
||||
displayName:
|
||||
description: DisplayName is a result image display-name label. This
|
||||
defaults to the output image name.
|
||||
type: string
|
||||
dockerConfig:
|
||||
description: DockerConfig describes how to access host docker daemon.
|
||||
properties:
|
||||
caFile:
|
||||
description: CAFile is the certificate authority file path for
|
||||
a TLS connection
|
||||
type: string
|
||||
certFile:
|
||||
description: CertFile is the certificate file path for a TLS
|
||||
connection
|
||||
type: string
|
||||
endPoint:
|
||||
description: Endpoint is the docker network endpoint or socket
|
||||
type: string
|
||||
keyFile:
|
||||
description: KeyFile is the key file path for a TLS connection
|
||||
type: string
|
||||
tlsVerify:
|
||||
description: TLSVerify indicates if TLS peer must be verified
|
||||
type: boolean
|
||||
useTLS:
|
||||
description: UseTLS indicates if TLS must be used
|
||||
type: boolean
|
||||
required:
|
||||
- caFile
|
||||
- certFile
|
||||
- endPoint
|
||||
- keyFile
|
||||
- tlsVerify
|
||||
- useTLS
|
||||
type: object
|
||||
dockerNetworkMode:
|
||||
description: DockerNetworkMode is used to set the docker network
|
||||
setting to --net=container:<id> when the builder is invoked from
|
||||
a container.
|
||||
type: string
|
||||
dropCapabilities:
|
||||
description: DropCapabilities contains a list of capabilities to
|
||||
drop when executing containers
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
environment:
|
||||
description: Environment is a map of environment variables to be
|
||||
passed to the image.
|
||||
items:
|
||||
description: EnvironmentSpec specifies a single environment variable.
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
value:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
- value
|
||||
type: object
|
||||
type: array
|
||||
excludeRegExp:
|
||||
description: ExcludeRegExp contains a string representation of the
|
||||
regular expression desired for deciding which files to exclude
|
||||
from the tar stream
|
||||
type: string
|
||||
export:
|
||||
description: Export Push the result image to specify image registry
|
||||
in tag
|
||||
type: boolean
|
||||
gitSecretRef:
|
||||
description: GitSecretRef is the BasicAuth Secret of Git Clone
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
hasOnBuild:
|
||||
description: HasOnBuild will be set to true if the builder image
|
||||
contains ONBUILD instructions
|
||||
type: boolean
|
||||
imageName:
|
||||
description: ImageName Contains the registry address and reponame,
|
||||
tag should set by field tag alone
|
||||
type: string
|
||||
imageScriptsUrl:
|
||||
description: ImageScriptsURL is the default location to find the
|
||||
assemble/run scripts for a builder image. This url can be a reference
|
||||
within the builder image if the scheme is specified as image://
|
||||
type: string
|
||||
imageWorkDir:
|
||||
description: ImageWorkDir is the default working directory for the
|
||||
builder image.
|
||||
type: string
|
||||
incremental:
|
||||
description: Incremental describes whether to try to perform incremental
|
||||
build.
|
||||
type: boolean
|
||||
incrementalAuthentication:
|
||||
description: IncrementalAuthentication holds the authentication
|
||||
information for pulling the previous image from private repositories
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
secretRef:
|
||||
description: LocalObjectReference contains enough information
|
||||
to let you locate the referenced object inside the same namespace.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
serverAddress:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
incrementalFromTag:
|
||||
description: IncrementalFromTag sets an alternative image tag to
|
||||
look for existing artifacts. Tag is used by default if this is
|
||||
not set.
|
||||
type: string
|
||||
injections:
|
||||
description: Injections specifies a list source/destination folders
|
||||
that are injected to the container that runs assemble. All files
|
||||
we inject will be truncated after the assemble script finishes.
|
||||
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
|
||||
isBinaryURL:
|
||||
description: IsBinaryURL explain the type of SourceURL. If it is
|
||||
IsBinaryURL, it will download the file directly without using
|
||||
git.
|
||||
type: boolean
|
||||
keepSymlinks:
|
||||
description: KeepSymlinks indicates to copy symlinks as symlinks.
|
||||
Default behavior is to follow symlinks and copy files by content.
|
||||
type: boolean
|
||||
labelNamespace:
|
||||
description: LabelNamespace provides the namespace under which the
|
||||
labels will be generated.
|
||||
type: string
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Labels specify labels and their values to be applied
|
||||
to the resulting image. Label keys must have non-zero length.
|
||||
The labels defined here override generated labels in case they
|
||||
have the same name.
|
||||
type: object
|
||||
layeredBuild:
|
||||
description: LayeredBuild describes if this is build which layered
|
||||
scripts and sources on top of BuilderImage.
|
||||
type: boolean
|
||||
nodeAffinityKey:
|
||||
description: The key of Node Affinity.
|
||||
type: string
|
||||
nodeAffinityValues:
|
||||
description: The values of Node Affinity.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
outputBuildResult:
|
||||
description: Whether output build result to status.
|
||||
type: boolean
|
||||
outputImageName:
|
||||
description: OutputImageName is a result image name without tag,
|
||||
default is latest. tag will append to ImageName in the end
|
||||
type: string
|
||||
preserveWorkingDir:
|
||||
description: PreserveWorkingDir describes if working directory should
|
||||
be left after processing.
|
||||
type: boolean
|
||||
previousImagePullPolicy:
|
||||
description: PreviousImagePullPolicy specifies when to pull the
|
||||
previously build image when doing incremental build
|
||||
type: string
|
||||
pullAuthentication:
|
||||
description: PullAuthentication holds the authentication information
|
||||
for pulling the Docker images from private repositories
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
secretRef:
|
||||
description: LocalObjectReference contains enough information
|
||||
to let you locate the referenced object inside the same namespace.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
serverAddress:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
pushAuthentication:
|
||||
description: PullAuthentication holds the authentication information
|
||||
for pulling the Docker images from private repositories
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
secretRef:
|
||||
description: LocalObjectReference contains enough information
|
||||
to let you locate the referenced object inside the same namespace.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
serverAddress:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
removePreviousImage:
|
||||
description: RemovePreviousImage describes if previous image should
|
||||
be removed after successful build. This applies only to incremental
|
||||
builds.
|
||||
type: boolean
|
||||
revisionId:
|
||||
description: The RevisionId is a branch name or a SHA-1 hash of
|
||||
every important thing about the commit
|
||||
type: string
|
||||
runImage:
|
||||
description: RunImage will trigger a "docker run ..." invocation
|
||||
of the produced image so the user can see if it operates as he
|
||||
would expect
|
||||
type: boolean
|
||||
runtimeArtifacts:
|
||||
description: RuntimeArtifacts specifies a list of source/destination
|
||||
pairs that will be copied from builder to a runtime image. Source
|
||||
can be a file or directory. Destination must be a directory. Regardless
|
||||
whether it is an absolute or relative path, it will be placed
|
||||
into image's WORKDIR. Destination also can be empty or equals
|
||||
to ".", in this case it just refers to a root of WORKDIR. In case
|
||||
it's empty, S2I will try to get this list from io.openshift.s2i.assemble-input-files
|
||||
label on a RuntimeImage.
|
||||
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
|
||||
runtimeAuthentication:
|
||||
description: RuntimeAuthentication holds the authentication information
|
||||
for pulling the runtime Docker images from private repositories.
|
||||
properties:
|
||||
email:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
secretRef:
|
||||
description: LocalObjectReference contains enough information
|
||||
to let you locate the referenced object inside the same namespace.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
|
||||
TODO: Add other useful fields. apiVersion, kind, uid?'
|
||||
type: string
|
||||
type: object
|
||||
serverAddress:
|
||||
type: string
|
||||
username:
|
||||
type: string
|
||||
type: object
|
||||
runtimeImage:
|
||||
description: RuntimeImage specifies the image that will be a base
|
||||
for resulting image and will be used for running an application.
|
||||
By default, BuilderImage is used for building and running, but
|
||||
the latter may be overridden.
|
||||
type: string
|
||||
runtimeImagePullPolicy:
|
||||
description: RuntimeImagePullPolicy specifies when to pull a runtime
|
||||
image.
|
||||
type: string
|
||||
scriptDownloadProxyConfig:
|
||||
description: ScriptDownloadProxyConfig optionally specifies the
|
||||
http and https proxy to use when downloading scripts
|
||||
properties:
|
||||
httpProxy:
|
||||
type: string
|
||||
httpsProxy:
|
||||
type: string
|
||||
type: object
|
||||
scriptsUrl:
|
||||
description: ScriptsURL is a URL describing where to fetch the S2I
|
||||
scripts from during build process. This url can be a reference
|
||||
within the builder image if the scheme is specified as image://
|
||||
type: string
|
||||
secretCode:
|
||||
description: SecretCode
|
||||
type: string
|
||||
securityOpt:
|
||||
description: SecurityOpt are passed as options to the docker containers
|
||||
launched by s2i.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
sourceUrl:
|
||||
description: SourceURL is url of the codes such as https://github.com/a/b.git
|
||||
type: string
|
||||
tag:
|
||||
description: Tag is a result image tag name.
|
||||
type: string
|
||||
taintKey:
|
||||
description: The name of taint.
|
||||
type: string
|
||||
usage:
|
||||
description: Usage allows for properly shortcircuiting s2i logic
|
||||
when `s2i usage` is invoked
|
||||
type: boolean
|
||||
workingDir:
|
||||
description: WorkingDir describes temporary directory used for downloading
|
||||
sources, scripts and tar operations.
|
||||
type: string
|
||||
workingSourceDir:
|
||||
description: WorkingSourceDir describes the subdirectory off of
|
||||
WorkingDir set up during the repo download that is later used
|
||||
as the root for ignore processing
|
||||
type: string
|
||||
required:
|
||||
- imageName
|
||||
- sourceUrl
|
||||
type: object
|
||||
fromTemplate:
|
||||
description: FromTemplate define some inputs from user
|
||||
properties:
|
||||
builderImage:
|
||||
description: BaseImage specify which version of this template to
|
||||
use
|
||||
type: string
|
||||
name:
|
||||
description: Name specify a template to use, so many fields in Config
|
||||
can left empty
|
||||
type: string
|
||||
parameters:
|
||||
description: Parameters must use with `template`, fill some parameters
|
||||
which template will use
|
||||
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
|
||||
type: object
|
||||
type: object
|
||||
status:
|
||||
description: S2iBuilderStatus defines the observed state of S2iBuilder
|
||||
properties:
|
||||
lastRunName:
|
||||
description: LastRunState return the name of the newest run of this
|
||||
builder
|
||||
type: string
|
||||
lastRunStartTime:
|
||||
description: LastRunStartTime return the startTime of the newest run
|
||||
of this builder
|
||||
format: date-time
|
||||
type: string
|
||||
lastRunState:
|
||||
description: LastRunState return the state of the newest run of this
|
||||
builder
|
||||
type: string
|
||||
runCount:
|
||||
description: RunCount represent the sum of s2irun of this builder
|
||||
type: integer
|
||||
required:
|
||||
- runCount
|
||||
type: object
|
||||
type: object
|
||||
version: v1alpha1
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
storage: true
|
||||
status:
|
||||
acceptedNames:
|
||||
kind: ""
|
||||
plural: ""
|
||||
conditions: []
|
||||
storedVersions: []
|
||||
141
config/crds/devops.kubesphere.io_s2ibuildertemplates.yaml
generated
Normal file
141
config/crds/devops.kubesphere.io_s2ibuildertemplates.yaml
generated
Normal file
@@ -0,0 +1,141 @@
|
||||
|
||||
---
|
||||
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: []
|
||||
181
config/crds/devops.kubesphere.io_s2iruns.yaml
generated
Normal file
181
config/crds/devops.kubesphere.io_s2iruns.yaml
generated
Normal file
@@ -0,0 +1,181 @@
|
||||
|
||||
---
|
||||
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: []
|
||||
6
go.mod
6
go.mod
@@ -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
|
||||
|
||||
2
go.sum
2
go.sum
@@ -276,8 +276,6 @@ github.com/kubesphere/application v0.0.0-20191210100950-18cc93526ab4 h1:pugSGmj8
|
||||
github.com/kubesphere/application v0.0.0-20191210100950-18cc93526ab4/go.mod h1:sILRE7W0CquRyC51JNRj4U7OP7CJl3o62TcX5E6IcWs=
|
||||
github.com/kubesphere/kiali v0.15.1-0.20191210080139-edbbad1ef779 h1:52StEbBn6dRFF2DE9DBmVt26JQu9j4DOwagLUq6gZWg=
|
||||
github.com/kubesphere/kiali v0.15.1-0.20191210080139-edbbad1ef779/go.mod h1:Y1EqeixoXkKkU8I+yvOfhdh21+8+etFE6wYOVT2XFdI=
|
||||
github.com/kubesphere/s2ioperator v0.0.14 h1:oShV/MSn8bwwnRzXU8bY3RH/V4k0TmCcKZ50B0Q9gEk=
|
||||
github.com/kubesphere/s2ioperator v0.0.14/go.mod h1:6stEM/ocFZxYhLYl2d5LRYE5WdggHMIX5ngJwloWR4g=
|
||||
github.com/kubesphere/sonargo v0.0.2 h1:hsSRE3sv3mkPcUAeSABdp7rtfcNW2zzeHXzFa01CTkU=
|
||||
github.com/kubesphere/sonargo v0.0.2/go.mod h1:ww8n9ANlDXhX5PBZ18iaRnCgEkXN0GMml3/KZXOZ11w=
|
||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
|
||||
|
||||
@@ -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
|
||||
|
||||
44
pkg/api/iam/authenticate.go
Normal file
44
pkg/api/iam/authenticate.go
Normal file
@@ -0,0 +1,44 @@
|
||||
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, "")
|
||||
}
|
||||
40
pkg/api/iam/user.go
Normal file
40
pkg/api/iam/user.go
Normal file
@@ -0,0 +1,40 @@
|
||||
package iam
|
||||
|
||||
import (
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Lang string `json:"lang,omitempty"`
|
||||
Description string `json:"description"`
|
||||
CreateTime time.Time `json:"create_time"`
|
||||
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"
|
||||
)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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 {
|
||||
58
pkg/apis/devops/v1alpha1/s2ibuilder_types_test.go
Normal file
58
pkg/apis/devops/v1alpha1/s2ibuilder_types_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
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 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 != "" {
|
||||
56
pkg/apis/devops/v1alpha1/s2ibuildertemplate_types_test.go
Normal file
56
pkg/apis/devops/v1alpha1/s2ibuildertemplate_types_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
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 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())
|
||||
}
|
||||
58
pkg/apis/devops/v1alpha1/s2irun_types_test.go
Normal file
58
pkg/apis/devops/v1alpha1/s2irun_types_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
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 v1alpha1
|
||||
|
||||
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())
|
||||
}
|
||||
757
pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go
generated
757
pkg/apis/devops/v1alpha1/zz_generated.deepcopy.go
generated
@@ -21,9 +21,257 @@ limitations under the License.
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AuthConfig) DeepCopyInto(out *AuthConfig) {
|
||||
*out = *in
|
||||
if in.SecretRef != nil {
|
||||
in, out := &in.SecretRef, &out.SecretRef
|
||||
*out = new(v1.LocalObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthConfig.
|
||||
func (in *AuthConfig) DeepCopy() *AuthConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AuthConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CGroupLimits) DeepCopyInto(out *CGroupLimits) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CGroupLimits.
|
||||
func (in *CGroupLimits) DeepCopy() *CGroupLimits {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CGroupLimits)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerConfig) DeepCopyInto(out *ContainerConfig) {
|
||||
*out = *in
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Env != nil {
|
||||
in, out := &in.Env, &out.Env
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerConfig.
|
||||
func (in *ContainerConfig) DeepCopy() *ContainerConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ContainerInfo) DeepCopyInto(out *ContainerInfo) {
|
||||
*out = *in
|
||||
if in.RuntimeArtifacts != nil {
|
||||
in, out := &in.RuntimeArtifacts, &out.RuntimeArtifacts
|
||||
*out = make([]VolumeSpec, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.BuildVolumes != nil {
|
||||
in, out := &in.BuildVolumes, &out.BuildVolumes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContainerInfo.
|
||||
func (in *ContainerInfo) DeepCopy() *ContainerInfo {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ContainerInfo)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DockerConfig) DeepCopyInto(out *DockerConfig) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerConfig.
|
||||
func (in *DockerConfig) DeepCopy() *DockerConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DockerConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DockerConfigEntry) DeepCopyInto(out *DockerConfigEntry) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerConfigEntry.
|
||||
func (in *DockerConfigEntry) DeepCopy() *DockerConfigEntry {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DockerConfigEntry)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DockerConfigJson) DeepCopyInto(out *DockerConfigJson) {
|
||||
*out = *in
|
||||
if in.Auths != nil {
|
||||
in, out := &in.Auths, &out.Auths
|
||||
*out = make(DockerConfigMap, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerConfigJson.
|
||||
func (in *DockerConfigJson) DeepCopy() *DockerConfigJson {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DockerConfigJson)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in DockerConfigMap) DeepCopyInto(out *DockerConfigMap) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(DockerConfigMap, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DockerConfigMap.
|
||||
func (in DockerConfigMap) DeepCopy() DockerConfigMap {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DockerConfigMap)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *EnvironmentSpec) DeepCopyInto(out *EnvironmentSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EnvironmentSpec.
|
||||
func (in *EnvironmentSpec) DeepCopy() *EnvironmentSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(EnvironmentSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Parameter) DeepCopyInto(out *Parameter) {
|
||||
*out = *in
|
||||
if in.OptValues != nil {
|
||||
in, out := &in.OptValues, &out.OptValues
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Parameter.
|
||||
func (in *Parameter) DeepCopy() *Parameter {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Parameter)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ProxyConfig) DeepCopyInto(out *ProxyConfig) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProxyConfig.
|
||||
func (in *ProxyConfig) DeepCopy() *ProxyConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ProxyConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iAutoScale) DeepCopyInto(out *S2iAutoScale) {
|
||||
*out = *in
|
||||
if in.InitReplicas != nil {
|
||||
in, out := &in.InitReplicas, &out.InitReplicas
|
||||
*out = new(int32)
|
||||
**out = **in
|
||||
}
|
||||
if in.Containers != nil {
|
||||
in, out := &in.Containers, &out.Containers
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iAutoScale.
|
||||
func (in *S2iAutoScale) DeepCopy() *S2iAutoScale {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iAutoScale)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBinary) DeepCopyInto(out *S2iBinary) {
|
||||
*out = *in
|
||||
@@ -120,3 +368,512 @@ func (in *S2iBinaryStatus) DeepCopy() *S2iBinaryStatus {
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuildResult) DeepCopyInto(out *S2iBuildResult) {
|
||||
*out = *in
|
||||
if in.ImageRepoTags != nil {
|
||||
in, out := &in.ImageRepoTags, &out.ImageRepoTags
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuildResult.
|
||||
func (in *S2iBuildResult) DeepCopy() *S2iBuildResult {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuildResult)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuildSource) DeepCopyInto(out *S2iBuildSource) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuildSource.
|
||||
func (in *S2iBuildSource) DeepCopy() *S2iBuildSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuildSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilder) DeepCopyInto(out *S2iBuilder) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilder.
|
||||
func (in *S2iBuilder) DeepCopy() *S2iBuilder {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilder)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iBuilder) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilderList) DeepCopyInto(out *S2iBuilderList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]S2iBuilder, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilderList.
|
||||
func (in *S2iBuilderList) DeepCopy() *S2iBuilderList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilderList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iBuilderList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilderSpec) DeepCopyInto(out *S2iBuilderSpec) {
|
||||
*out = *in
|
||||
if in.Config != nil {
|
||||
in, out := &in.Config, &out.Config
|
||||
*out = new(S2iConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.FromTemplate != nil {
|
||||
in, out := &in.FromTemplate, &out.FromTemplate
|
||||
*out = new(UserDefineTemplate)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilderSpec.
|
||||
func (in *S2iBuilderSpec) DeepCopy() *S2iBuilderSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilderSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilderStatus) DeepCopyInto(out *S2iBuilderStatus) {
|
||||
*out = *in
|
||||
if in.LastRunName != nil {
|
||||
in, out := &in.LastRunName, &out.LastRunName
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.LastRunStartTime != nil {
|
||||
in, out := &in.LastRunStartTime, &out.LastRunStartTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilderStatus.
|
||||
func (in *S2iBuilderStatus) DeepCopy() *S2iBuilderStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilderStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilderTemplate) DeepCopyInto(out *S2iBuilderTemplate) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilderTemplate.
|
||||
func (in *S2iBuilderTemplate) DeepCopy() *S2iBuilderTemplate {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilderTemplate)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iBuilderTemplate) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilderTemplateList) DeepCopyInto(out *S2iBuilderTemplateList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]S2iBuilderTemplate, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilderTemplateList.
|
||||
func (in *S2iBuilderTemplateList) DeepCopy() *S2iBuilderTemplateList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilderTemplateList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iBuilderTemplateList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilderTemplateSpec) DeepCopyInto(out *S2iBuilderTemplateSpec) {
|
||||
*out = *in
|
||||
if in.ContainerInfo != nil {
|
||||
in, out := &in.ContainerInfo, &out.ContainerInfo
|
||||
*out = make([]ContainerInfo, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Parameters != nil {
|
||||
in, out := &in.Parameters, &out.Parameters
|
||||
*out = make([]Parameter, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilderTemplateSpec.
|
||||
func (in *S2iBuilderTemplateSpec) DeepCopy() *S2iBuilderTemplateSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilderTemplateSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iBuilderTemplateStatus) DeepCopyInto(out *S2iBuilderTemplateStatus) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iBuilderTemplateStatus.
|
||||
func (in *S2iBuilderTemplateStatus) DeepCopy() *S2iBuilderTemplateStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iBuilderTemplateStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iConfig) DeepCopyInto(out *S2iConfig) {
|
||||
*out = *in
|
||||
if in.RuntimeAuthentication != nil {
|
||||
in, out := &in.RuntimeAuthentication, &out.RuntimeAuthentication
|
||||
*out = new(AuthConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.RuntimeArtifacts != nil {
|
||||
in, out := &in.RuntimeArtifacts, &out.RuntimeArtifacts
|
||||
*out = make([]VolumeSpec, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.DockerConfig != nil {
|
||||
in, out := &in.DockerConfig, &out.DockerConfig
|
||||
*out = new(DockerConfig)
|
||||
**out = **in
|
||||
}
|
||||
if in.PullAuthentication != nil {
|
||||
in, out := &in.PullAuthentication, &out.PullAuthentication
|
||||
*out = new(AuthConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.PushAuthentication != nil {
|
||||
in, out := &in.PushAuthentication, &out.PushAuthentication
|
||||
*out = new(AuthConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.IncrementalAuthentication != nil {
|
||||
in, out := &in.IncrementalAuthentication, &out.IncrementalAuthentication
|
||||
*out = new(AuthConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Environment != nil {
|
||||
in, out := &in.Environment, &out.Environment
|
||||
*out = make([]EnvironmentSpec, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Injections != nil {
|
||||
in, out := &in.Injections, &out.Injections
|
||||
*out = make([]VolumeSpec, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.CGroupLimits != nil {
|
||||
in, out := &in.CGroupLimits, &out.CGroupLimits
|
||||
*out = new(CGroupLimits)
|
||||
**out = **in
|
||||
}
|
||||
if in.DropCapabilities != nil {
|
||||
in, out := &in.DropCapabilities, &out.DropCapabilities
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ScriptDownloadProxyConfig != nil {
|
||||
in, out := &in.ScriptDownloadProxyConfig, &out.ScriptDownloadProxyConfig
|
||||
*out = new(ProxyConfig)
|
||||
**out = **in
|
||||
}
|
||||
if in.BuildVolumes != nil {
|
||||
in, out := &in.BuildVolumes, &out.BuildVolumes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.SecurityOpt != nil {
|
||||
in, out := &in.SecurityOpt, &out.SecurityOpt
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AddHost != nil {
|
||||
in, out := &in.AddHost, &out.AddHost
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.GitSecretRef != nil {
|
||||
in, out := &in.GitSecretRef, &out.GitSecretRef
|
||||
*out = new(v1.LocalObjectReference)
|
||||
**out = **in
|
||||
}
|
||||
if in.NodeAffinityValues != nil {
|
||||
in, out := &in.NodeAffinityValues, &out.NodeAffinityValues
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iConfig.
|
||||
func (in *S2iConfig) DeepCopy() *S2iConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iRun) DeepCopyInto(out *S2iRun) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iRun.
|
||||
func (in *S2iRun) DeepCopy() *S2iRun {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iRun)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iRun) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iRunList) DeepCopyInto(out *S2iRunList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]S2iRun, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iRunList.
|
||||
func (in *S2iRunList) DeepCopy() *S2iRunList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iRunList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *S2iRunList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iRunSpec) DeepCopyInto(out *S2iRunSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iRunSpec.
|
||||
func (in *S2iRunSpec) DeepCopy() *S2iRunSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iRunSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *S2iRunStatus) DeepCopyInto(out *S2iRunStatus) {
|
||||
*out = *in
|
||||
if in.StartTime != nil {
|
||||
in, out := &in.StartTime, &out.StartTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.CompletionTime != nil {
|
||||
in, out := &in.CompletionTime, &out.CompletionTime
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.S2iBuildResult != nil {
|
||||
in, out := &in.S2iBuildResult, &out.S2iBuildResult
|
||||
*out = new(S2iBuildResult)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.S2iBuildSource != nil {
|
||||
in, out := &in.S2iBuildSource, &out.S2iBuildSource
|
||||
*out = new(S2iBuildSource)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new S2iRunStatus.
|
||||
func (in *S2iRunStatus) DeepCopy() *S2iRunStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(S2iRunStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UserDefineTemplate) DeepCopyInto(out *UserDefineTemplate) {
|
||||
*out = *in
|
||||
if in.Parameters != nil {
|
||||
in, out := &in.Parameters, &out.Parameters
|
||||
*out = make([]Parameter, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UserDefineTemplate.
|
||||
func (in *UserDefineTemplate) DeepCopy() *UserDefineTemplate {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UserDefineTemplate)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *VolumeSpec) DeepCopyInto(out *VolumeSpec) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeSpec.
|
||||
func (in *VolumeSpec) DeepCopy() *VolumeSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(VolumeSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -1,18 +1,38 @@
|
||||
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 New(deps *Dependencies) *APIServer {
|
||||
func (s *APIServer) Run(stopCh <-chan struct{}) error {
|
||||
|
||||
server := &APIServer{}
|
||||
err := s.waitForResourceSync(stopCh)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return server
|
||||
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 (s *APIServer) InstallKubeSphereAPIs() {
|
||||
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"},
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
resourcev1alpha3.AddWebService(s.container, s.kubeClient)
|
||||
}
|
||||
|
||||
func (s *APIServer) Serve() error {
|
||||
panic("implement me")
|
||||
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"))
|
||||
}
|
||||
|
||||
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 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
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/spf13/viper"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/alerting"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
@@ -49,12 +49,100 @@ import (
|
||||
//
|
||||
// --mysql-username root --mysql-password password
|
||||
//
|
||||
// we will `root:password@mysql.kubesphere-system.svc` as input, case
|
||||
// we will `root:password@mysql.kubesphere-system.svc` as input, cause
|
||||
// mysql-host is missing in command line flags, all other mysql command line flags
|
||||
// will be ignored.
|
||||
|
||||
const (
|
||||
// DefaultConfigurationName is the default name of configuration
|
||||
defaultConfigurationName = "kubesphere"
|
||||
|
||||
// DefaultConfigurationPath the default location of the configuration file
|
||||
defaultConfigurationPath = "/etc/kubesphere"
|
||||
)
|
||||
|
||||
// Config defines everything needed for apiserver to deal with external services
|
||||
type Config struct {
|
||||
MySQLOptions *mysql.Options `json:"mysql,omitempty" yaml:"mysql,omitempty" mapstructure:"mysql"`
|
||||
DevopsOptions *jenkins.Options `json:"devops,omitempty" yaml:"devops,omitempty" mapstructure:"devops"`
|
||||
SonarQubeOptions *sonarqube.Options `json:"sonarqube,omitempty" yaml:"sonarQube,omitempty" mapstructure:"sonarqube"`
|
||||
KubernetesOptions *k8s.KubernetesOptions `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"`
|
||||
ServiceMeshOptions *servicemesh.Options `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"`
|
||||
LdapOptions *ldap.Options `json:"ldap,omitempty" yaml:"ldap,omitempty" mapstructure:"ldap"`
|
||||
RedisOptions *cache.Options `json:"redis,omitempty" yaml:"redis,omitempty" mapstructure:"redis"`
|
||||
S3Options *s3.Options `json:"s3,omitempty" yaml:"s3,omitempty" mapstructure:"s3"`
|
||||
OpenPitrixOptions *openpitrix.Options `json:"openpitrix,omitempty" yaml:"openpitrix,omitempty" mapstructure:"openpitrix"`
|
||||
MonitoringOptions *prometheus.Options `json:"monitoring,omitempty" yaml:"monitoring,omitempty" mapstructure:"monitoring"`
|
||||
LoggingOptions *elasticsearch.Options `json:"logging,omitempty" yaml:"logging,omitempty" mapstructure:"logging"`
|
||||
|
||||
// Options below are only loaded from configuration file, no command line flags for these options now.
|
||||
KubeSphereOptions *kubesphere.Options `json:"-" yaml:"kubesphere,omitempty" mapstructure:"kubesphere"`
|
||||
|
||||
AuthenticateOptions *iam.AuthenticationOptions `json:"authenticate,omitempty" yaml:"authenticate,omitempty" mapstructure:"authenticate"`
|
||||
|
||||
// Options used for enabling components, not actually used now. Once we switch Alerting/Notification API to kubesphere,
|
||||
// we can add these options to kubesphere command lines
|
||||
AlertingOptions *alerting.Options `json:"alerting,omitempty" yaml:"alerting,omitempty" mapstructure:"alerting"`
|
||||
NotificationOptions *notification.Options `json:"notification,omitempty" yaml:"notification,omitempty" mapstructure:"notification"`
|
||||
}
|
||||
|
||||
// newConfig creates a default non-empty Config
|
||||
func New() *Config {
|
||||
return &Config{
|
||||
MySQLOptions: mysql.NewMySQLOptions(),
|
||||
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
||||
LdapOptions: ldap.NewOptions(),
|
||||
RedisOptions: cache.NewRedisOptions(),
|
||||
S3Options: s3.NewS3Options(),
|
||||
OpenPitrixOptions: openpitrix.NewOptions(),
|
||||
MonitoringOptions: prometheus.NewPrometheusOptions(),
|
||||
KubeSphereOptions: kubesphere.NewKubeSphereOptions(),
|
||||
AlertingOptions: alerting.NewAlertingOptions(),
|
||||
NotificationOptions: notification.NewNotificationOptions(),
|
||||
LoggingOptions: elasticsearch.NewElasticSearchOptions(),
|
||||
AuthenticateOptions: iam.NewAuthenticateOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
// TryLoadFromDisk loads configuration from default location after server startup
|
||||
// return nil error if configuration file not exists
|
||||
func TryLoadFromDisk() (*Config, error) {
|
||||
viper.SetConfigName(defaultConfigurationName)
|
||||
viper.AddConfigPath(defaultConfigurationPath)
|
||||
|
||||
// Load from current working directory, only used for debugging
|
||||
viper.AddConfigPath(".")
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
return nil, err
|
||||
} else {
|
||||
return nil, fmt.Errorf("error parsing configuration file %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
conf := New()
|
||||
if err := viper.Unmarshal(conf); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
// make sure kubesphere options always exists
|
||||
if conf.KubeSphereOptions == nil {
|
||||
conf.KubeSphereOptions = kubesphere.NewKubeSphereOptions()
|
||||
} else {
|
||||
ksOptions := kubesphere.NewKubeSphereOptions()
|
||||
conf.KubeSphereOptions.ApplyTo(ksOptions)
|
||||
conf.KubeSphereOptions = ksOptions
|
||||
}
|
||||
}
|
||||
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
// InstallAPI installs api for config
|
||||
func InstallAPI(c *restful.Container) {
|
||||
func (conf *Config) InstallAPI(c *restful.Container) {
|
||||
ws := runtime.NewWebService(schema.GroupVersion{
|
||||
Group: "",
|
||||
Version: "v1alpha1",
|
||||
@@ -62,11 +150,8 @@ func InstallAPI(c *restful.Container) {
|
||||
|
||||
ws.Route(ws.GET("/configz").
|
||||
To(func(request *restful.Request, response *restful.Response) {
|
||||
var conf = *sharedConfig
|
||||
|
||||
conf.stripEmptyOptions()
|
||||
|
||||
response.WriteAsJson(convertToMap(&conf))
|
||||
response.WriteAsJson(conf.toMap())
|
||||
}).
|
||||
Doc("Get system components configuration").
|
||||
Produces(restful.MIME_JSON).
|
||||
@@ -78,7 +163,7 @@ func InstallAPI(c *restful.Container) {
|
||||
|
||||
// convertToMap simply converts config to map[string]bool
|
||||
// to hide sensitive information
|
||||
func convertToMap(conf *Config) map[string]bool {
|
||||
func (conf *Config) toMap() map[string]bool {
|
||||
result := make(map[string]bool, 0)
|
||||
|
||||
if conf == nil {
|
||||
@@ -103,206 +188,56 @@ func convertToMap(conf *Config) map[string]bool {
|
||||
return result
|
||||
}
|
||||
|
||||
// Load loads configuration after setup
|
||||
func Load() error {
|
||||
sharedConfig = newConfig()
|
||||
|
||||
viper.SetConfigName(DefaultConfigurationName)
|
||||
viper.AddConfigPath(DefaultConfigurationPath)
|
||||
viper.AddConfigPath(".")
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||
klog.Warning("configuration file not found")
|
||||
return nil
|
||||
} else {
|
||||
panic(fmt.Errorf("error parsing configuration file %s", err))
|
||||
}
|
||||
func (conf *Config) stripEmptyOptions() {
|
||||
if conf.MySQLOptions != nil && conf.MySQLOptions.Host == "" {
|
||||
conf.MySQLOptions = nil
|
||||
}
|
||||
|
||||
conf := newConfig()
|
||||
if err := viper.Unmarshal(conf); err != nil {
|
||||
klog.Error(fmt.Errorf("error unmarshal configuration %v", err))
|
||||
return err
|
||||
} else {
|
||||
// make sure kubesphere options always exists
|
||||
if conf.KubeSphereOptions == nil {
|
||||
conf.KubeSphereOptions = kubesphere.NewKubeSphereOptions()
|
||||
} else {
|
||||
ksOptions := kubesphere.NewKubeSphereOptions()
|
||||
conf.KubeSphereOptions.ApplyTo(ksOptions)
|
||||
conf.KubeSphereOptions = ksOptions
|
||||
}
|
||||
|
||||
conf.Apply(shadowConfig)
|
||||
sharedConfig = conf
|
||||
if conf.RedisOptions != nil && conf.RedisOptions.RedisURL == "" {
|
||||
conf.RedisOptions = nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultConfigurationName is the default name of configuration
|
||||
DefaultConfigurationName = "kubesphere"
|
||||
|
||||
// DefaultConfigurationPath the default location of the configuration file
|
||||
DefaultConfigurationPath = "/etc/kubesphere"
|
||||
)
|
||||
|
||||
var (
|
||||
// sharedConfig holds configuration across kubesphere
|
||||
sharedConfig *Config
|
||||
|
||||
// shadowConfig contains options from commandline options
|
||||
shadowConfig = &Config{}
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
MySQLOptions *mysql.Options `json:"mysql,omitempty" yaml:"mysql,omitempty" mapstructure:"mysql"`
|
||||
DevopsOptions *jenkins.Options `json:"devops,omitempty" yaml:"devops,omitempty" mapstructure:"devops"`
|
||||
SonarQubeOptions *sonarqube.Options `json:"sonarqube,omitempty" yaml:"sonarQube,omitempty" mapstructure:"sonarqube"`
|
||||
KubernetesOptions *k8s.KubernetesOptions `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"`
|
||||
ServiceMeshOptions *servicemesh.Options `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"`
|
||||
LdapOptions *ldap.Options `json:"ldap,omitempty" yaml:"ldap,omitempty" mapstructure:"ldap"`
|
||||
RedisOptions *cache.Options `json:"redis,omitempty" yaml:"redis,omitempty" mapstructure:"redis"`
|
||||
S3Options *s3.Options `json:"s3,omitempty" yaml:"s3,omitempty" mapstructure:"s3"`
|
||||
OpenPitrixOptions *openpitrix.Options `json:"openpitrix,omitempty" yaml:"openpitrix,omitempty" mapstructure:"openpitrix"`
|
||||
MonitoringOptions *prometheus.Options `json:"monitoring,omitempty" yaml:"monitoring,omitempty" mapstructure:"monitoring"`
|
||||
LoggingOptions *elasticsearch.Options `json:"logging,omitempty" yaml:"logging,omitempty" mapstructure:"logging"`
|
||||
|
||||
// Options below are only loaded from configuration file, no command line flags for these options now.
|
||||
KubeSphereOptions *kubesphere.Options `json:"-" yaml:"kubesphere,omitempty" mapstructure:"kubesphere"`
|
||||
|
||||
// Options used for enabling components, not actually used now. Once we switch Alerting/Notification API to kubesphere,
|
||||
// we can add these options to kubesphere command lines
|
||||
AlertingOptions *alerting.Options `json:"alerting,omitempty" yaml:"alerting,omitempty" mapstructure:"alerting"`
|
||||
NotificationOptions *notification.Options `json:"notification,omitempty" yaml:"notification,omitempty" mapstructure:"notification"`
|
||||
}
|
||||
|
||||
func newConfig() *Config {
|
||||
return &Config{
|
||||
MySQLOptions: mysql.NewMySQLOptions(),
|
||||
DevopsOptions: jenkins.NewDevopsOptions(),
|
||||
SonarQubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||
KubernetesOptions: k8s.NewKubernetesOptions(),
|
||||
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
|
||||
LdapOptions: ldap.NewOptions(),
|
||||
RedisOptions: cache.NewRedisOptions(),
|
||||
S3Options: s3.NewS3Options(),
|
||||
OpenPitrixOptions: openpitrix.NewOptions(),
|
||||
MonitoringOptions: prometheus.NewPrometheusOptions(),
|
||||
KubeSphereOptions: kubesphere.NewKubeSphereOptions(),
|
||||
AlertingOptions: alerting.NewAlertingOptions(),
|
||||
NotificationOptions: notification.NewNotificationOptions(),
|
||||
LoggingOptions: elasticsearch.NewElasticSearchOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
func Get() *Config {
|
||||
return sharedConfig
|
||||
}
|
||||
|
||||
func (c *Config) Apply(conf *Config) {
|
||||
shadowConfig = conf
|
||||
|
||||
if conf.LoggingOptions != nil {
|
||||
conf.LoggingOptions.ApplyTo(c.LoggingOptions)
|
||||
if conf.DevopsOptions != nil && conf.DevopsOptions.Host == "" {
|
||||
conf.DevopsOptions = nil
|
||||
}
|
||||
|
||||
if conf.KubeSphereOptions != nil {
|
||||
conf.KubeSphereOptions.ApplyTo(c.KubeSphereOptions)
|
||||
if conf.MonitoringOptions != nil && conf.MonitoringOptions.Endpoint == "" &&
|
||||
conf.MonitoringOptions.SecondaryEndpoint == "" {
|
||||
conf.MonitoringOptions = nil
|
||||
}
|
||||
|
||||
if conf.MonitoringOptions != nil {
|
||||
conf.MonitoringOptions.ApplyTo(c.MonitoringOptions)
|
||||
}
|
||||
if conf.OpenPitrixOptions != nil {
|
||||
conf.OpenPitrixOptions.ApplyTo(c.OpenPitrixOptions)
|
||||
if conf.SonarQubeOptions != nil && conf.SonarQubeOptions.Host == "" {
|
||||
conf.SonarQubeOptions = nil
|
||||
}
|
||||
|
||||
if conf.S3Options != nil {
|
||||
conf.S3Options.ApplyTo(c.S3Options)
|
||||
if conf.LdapOptions != nil && conf.LdapOptions.Host == "" {
|
||||
conf.LdapOptions = nil
|
||||
}
|
||||
|
||||
if conf.RedisOptions != nil {
|
||||
conf.RedisOptions.ApplyTo(c.RedisOptions)
|
||||
if conf.OpenPitrixOptions != nil && conf.OpenPitrixOptions.IsEmpty() {
|
||||
conf.OpenPitrixOptions = nil
|
||||
}
|
||||
|
||||
if conf.LdapOptions != nil {
|
||||
conf.LdapOptions.ApplyTo(c.LdapOptions)
|
||||
if conf.ServiceMeshOptions != nil && conf.ServiceMeshOptions.IstioPilotHost == "" &&
|
||||
conf.ServiceMeshOptions.ServicemeshPrometheusHost == "" &&
|
||||
conf.ServiceMeshOptions.JaegerQueryHost == "" {
|
||||
conf.ServiceMeshOptions = nil
|
||||
}
|
||||
|
||||
if conf.ServiceMeshOptions != nil {
|
||||
conf.ServiceMeshOptions.ApplyTo(c.ServiceMeshOptions)
|
||||
if conf.S3Options != nil && conf.S3Options.Endpoint == "" {
|
||||
conf.S3Options = nil
|
||||
}
|
||||
|
||||
if conf.KubernetesOptions != nil {
|
||||
conf.KubernetesOptions.ApplyTo(c.KubernetesOptions)
|
||||
if conf.AlertingOptions != nil && conf.AlertingOptions.Endpoint == "" {
|
||||
conf.AlertingOptions = nil
|
||||
}
|
||||
|
||||
if conf.SonarQubeOptions != nil {
|
||||
conf.SonarQubeOptions.ApplyTo(c.SonarQubeOptions)
|
||||
if conf.LoggingOptions != nil && conf.LoggingOptions.Host == "" {
|
||||
conf.LoggingOptions = nil
|
||||
}
|
||||
|
||||
if conf.DevopsOptions != nil {
|
||||
conf.DevopsOptions.ApplyTo(c.DevopsOptions)
|
||||
}
|
||||
|
||||
if conf.MySQLOptions != nil {
|
||||
conf.MySQLOptions.ApplyTo(c.MySQLOptions)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) stripEmptyOptions() {
|
||||
if c.MySQLOptions != nil && c.MySQLOptions.Host == "" {
|
||||
c.MySQLOptions = nil
|
||||
}
|
||||
|
||||
if c.RedisOptions != nil && c.RedisOptions.RedisURL == "" {
|
||||
c.RedisOptions = nil
|
||||
}
|
||||
|
||||
if c.DevopsOptions != nil && c.DevopsOptions.Host == "" {
|
||||
c.DevopsOptions = nil
|
||||
}
|
||||
|
||||
if c.MonitoringOptions != nil && c.MonitoringOptions.Endpoint == "" &&
|
||||
c.MonitoringOptions.SecondaryEndpoint == "" {
|
||||
c.MonitoringOptions = nil
|
||||
}
|
||||
|
||||
if c.SonarQubeOptions != nil && c.SonarQubeOptions.Host == "" {
|
||||
c.SonarQubeOptions = nil
|
||||
}
|
||||
|
||||
if c.LdapOptions != nil && c.LdapOptions.Host == "" {
|
||||
c.LdapOptions = nil
|
||||
}
|
||||
|
||||
if c.OpenPitrixOptions != nil && c.OpenPitrixOptions.IsEmpty() {
|
||||
c.OpenPitrixOptions = nil
|
||||
}
|
||||
|
||||
if c.ServiceMeshOptions != nil && c.ServiceMeshOptions.IstioPilotHost == "" &&
|
||||
c.ServiceMeshOptions.ServicemeshPrometheusHost == "" &&
|
||||
c.ServiceMeshOptions.JaegerQueryHost == "" {
|
||||
c.ServiceMeshOptions = nil
|
||||
}
|
||||
|
||||
if c.S3Options != nil && c.S3Options.Endpoint == "" {
|
||||
c.S3Options = nil
|
||||
}
|
||||
|
||||
if c.AlertingOptions != nil && c.AlertingOptions.Endpoint == "" {
|
||||
c.AlertingOptions = nil
|
||||
}
|
||||
|
||||
if c.LoggingOptions != nil && c.LoggingOptions.Host == "" {
|
||||
c.LoggingOptions = nil
|
||||
}
|
||||
|
||||
if c.NotificationOptions != nil && c.NotificationOptions.Endpoint == "" {
|
||||
c.NotificationOptions = nil
|
||||
if conf.NotificationOptions != nil && conf.NotificationOptions.Endpoint == "" {
|
||||
conf.NotificationOptions = nil
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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: ¬ification.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"
|
||||
|
||||
@@ -6,6 +6,7 @@ const (
|
||||
FieldName = "name"
|
||||
FieldCreationTimeStamp = "creationTimestamp"
|
||||
FieldLastUpdateTimestamp = "lastUpdateTimestamp"
|
||||
FieldLabel = "label"
|
||||
FieldNamespace = "namespace"
|
||||
FieldStatus = "status"
|
||||
FieldApplication = "application"
|
||||
|
||||
@@ -27,6 +27,9 @@ import (
|
||||
type DevopsV1alpha1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
S2iBinariesGetter
|
||||
S2iBuildersGetter
|
||||
S2iBuilderTemplatesGetter
|
||||
S2iRunsGetter
|
||||
}
|
||||
|
||||
// DevopsV1alpha1Client is used to interact with features provided by the devops.kubesphere.io group.
|
||||
@@ -38,6 +41,18 @@ func (c *DevopsV1alpha1Client) S2iBinaries(namespace string) S2iBinaryInterface
|
||||
return newS2iBinaries(c, namespace)
|
||||
}
|
||||
|
||||
func (c *DevopsV1alpha1Client) S2iBuilders(namespace string) S2iBuilderInterface {
|
||||
return newS2iBuilders(c, namespace)
|
||||
}
|
||||
|
||||
func (c *DevopsV1alpha1Client) S2iBuilderTemplates() S2iBuilderTemplateInterface {
|
||||
return newS2iBuilderTemplates(c)
|
||||
}
|
||||
|
||||
func (c *DevopsV1alpha1Client) S2iRuns(namespace string) S2iRunInterface {
|
||||
return newS2iRuns(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new DevopsV1alpha1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*DevopsV1alpha1Client, error) {
|
||||
config := *c
|
||||
|
||||
@@ -32,6 +32,18 @@ func (c *FakeDevopsV1alpha1) S2iBinaries(namespace string) v1alpha1.S2iBinaryInt
|
||||
return &FakeS2iBinaries{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeDevopsV1alpha1) S2iBuilders(namespace string) v1alpha1.S2iBuilderInterface {
|
||||
return &FakeS2iBuilders{c, namespace}
|
||||
}
|
||||
|
||||
func (c *FakeDevopsV1alpha1) S2iBuilderTemplates() v1alpha1.S2iBuilderTemplateInterface {
|
||||
return &FakeS2iBuilderTemplates{c}
|
||||
}
|
||||
|
||||
func (c *FakeDevopsV1alpha1) S2iRuns(namespace string) v1alpha1.S2iRunInterface {
|
||||
return &FakeS2iRuns{c, namespace}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeDevopsV1alpha1) RESTClient() rest.Interface {
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// FakeS2iBuilders implements S2iBuilderInterface
|
||||
type FakeS2iBuilders struct {
|
||||
Fake *FakeDevopsV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var s2ibuildersResource = schema.GroupVersionResource{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"}
|
||||
|
||||
var s2ibuildersKind = schema.GroupVersionKind{Group: "devops.kubesphere.io", Version: "v1alpha1", Kind: "S2iBuilder"}
|
||||
|
||||
// Get takes name of the s2iBuilder, and returns the corresponding s2iBuilder object, and an error if there is any.
|
||||
func (c *FakeS2iBuilders) Get(name string, options v1.GetOptions) (result *v1alpha1.S2iBuilder, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(s2ibuildersResource, c.ns, name), &v1alpha1.S2iBuilder{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilder), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of S2iBuilders that match those selectors.
|
||||
func (c *FakeS2iBuilders) List(opts v1.ListOptions) (result *v1alpha1.S2iBuilderList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(s2ibuildersResource, s2ibuildersKind, c.ns, opts), &v1alpha1.S2iBuilderList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.S2iBuilderList{ListMeta: obj.(*v1alpha1.S2iBuilderList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.S2iBuilderList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested s2iBuilders.
|
||||
func (c *FakeS2iBuilders) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(s2ibuildersResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a s2iBuilder and creates it. Returns the server's representation of the s2iBuilder, and an error, if there is any.
|
||||
func (c *FakeS2iBuilders) Create(s2iBuilder *v1alpha1.S2iBuilder) (result *v1alpha1.S2iBuilder, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(s2ibuildersResource, c.ns, s2iBuilder), &v1alpha1.S2iBuilder{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilder), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a s2iBuilder and updates it. Returns the server's representation of the s2iBuilder, and an error, if there is any.
|
||||
func (c *FakeS2iBuilders) Update(s2iBuilder *v1alpha1.S2iBuilder) (result *v1alpha1.S2iBuilder, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(s2ibuildersResource, c.ns, s2iBuilder), &v1alpha1.S2iBuilder{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilder), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeS2iBuilders) UpdateStatus(s2iBuilder *v1alpha1.S2iBuilder) (*v1alpha1.S2iBuilder, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(s2ibuildersResource, "status", c.ns, s2iBuilder), &v1alpha1.S2iBuilder{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilder), err
|
||||
}
|
||||
|
||||
// Delete takes name of the s2iBuilder and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeS2iBuilders) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(s2ibuildersResource, c.ns, name), &v1alpha1.S2iBuilder{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeS2iBuilders) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(s2ibuildersResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.S2iBuilderList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched s2iBuilder.
|
||||
func (c *FakeS2iBuilders) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.S2iBuilder, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(s2ibuildersResource, c.ns, name, pt, data, subresources...), &v1alpha1.S2iBuilder{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilder), err
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// FakeS2iBuilderTemplates implements S2iBuilderTemplateInterface
|
||||
type FakeS2iBuilderTemplates struct {
|
||||
Fake *FakeDevopsV1alpha1
|
||||
}
|
||||
|
||||
var s2ibuildertemplatesResource = schema.GroupVersionResource{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"}
|
||||
|
||||
var s2ibuildertemplatesKind = schema.GroupVersionKind{Group: "devops.kubesphere.io", Version: "v1alpha1", Kind: "S2iBuilderTemplate"}
|
||||
|
||||
// Get takes name of the s2iBuilderTemplate, and returns the corresponding s2iBuilderTemplate object, and an error if there is any.
|
||||
func (c *FakeS2iBuilderTemplates) Get(name string, options v1.GetOptions) (result *v1alpha1.S2iBuilderTemplate, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(s2ibuildertemplatesResource, name), &v1alpha1.S2iBuilderTemplate{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilderTemplate), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of S2iBuilderTemplates that match those selectors.
|
||||
func (c *FakeS2iBuilderTemplates) List(opts v1.ListOptions) (result *v1alpha1.S2iBuilderTemplateList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(s2ibuildertemplatesResource, s2ibuildertemplatesKind, opts), &v1alpha1.S2iBuilderTemplateList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.S2iBuilderTemplateList{ListMeta: obj.(*v1alpha1.S2iBuilderTemplateList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.S2iBuilderTemplateList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested s2iBuilderTemplates.
|
||||
func (c *FakeS2iBuilderTemplates) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(s2ibuildertemplatesResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a s2iBuilderTemplate and creates it. Returns the server's representation of the s2iBuilderTemplate, and an error, if there is any.
|
||||
func (c *FakeS2iBuilderTemplates) Create(s2iBuilderTemplate *v1alpha1.S2iBuilderTemplate) (result *v1alpha1.S2iBuilderTemplate, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(s2ibuildertemplatesResource, s2iBuilderTemplate), &v1alpha1.S2iBuilderTemplate{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilderTemplate), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a s2iBuilderTemplate and updates it. Returns the server's representation of the s2iBuilderTemplate, and an error, if there is any.
|
||||
func (c *FakeS2iBuilderTemplates) Update(s2iBuilderTemplate *v1alpha1.S2iBuilderTemplate) (result *v1alpha1.S2iBuilderTemplate, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(s2ibuildertemplatesResource, s2iBuilderTemplate), &v1alpha1.S2iBuilderTemplate{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilderTemplate), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeS2iBuilderTemplates) UpdateStatus(s2iBuilderTemplate *v1alpha1.S2iBuilderTemplate) (*v1alpha1.S2iBuilderTemplate, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(s2ibuildertemplatesResource, "status", s2iBuilderTemplate), &v1alpha1.S2iBuilderTemplate{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilderTemplate), err
|
||||
}
|
||||
|
||||
// Delete takes name of the s2iBuilderTemplate and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeS2iBuilderTemplates) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(s2ibuildertemplatesResource, name), &v1alpha1.S2iBuilderTemplate{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeS2iBuilderTemplates) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(s2ibuildertemplatesResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.S2iBuilderTemplateList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched s2iBuilderTemplate.
|
||||
func (c *FakeS2iBuilderTemplates) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.S2iBuilderTemplate, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(s2ibuildertemplatesResource, name, pt, data, subresources...), &v1alpha1.S2iBuilderTemplate{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iBuilderTemplate), err
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// FakeS2iRuns implements S2iRunInterface
|
||||
type FakeS2iRuns struct {
|
||||
Fake *FakeDevopsV1alpha1
|
||||
ns string
|
||||
}
|
||||
|
||||
var s2irunsResource = schema.GroupVersionResource{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2iruns"}
|
||||
|
||||
var s2irunsKind = schema.GroupVersionKind{Group: "devops.kubesphere.io", Version: "v1alpha1", Kind: "S2iRun"}
|
||||
|
||||
// Get takes name of the s2iRun, and returns the corresponding s2iRun object, and an error if there is any.
|
||||
func (c *FakeS2iRuns) Get(name string, options v1.GetOptions) (result *v1alpha1.S2iRun, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewGetAction(s2irunsResource, c.ns, name), &v1alpha1.S2iRun{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iRun), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of S2iRuns that match those selectors.
|
||||
func (c *FakeS2iRuns) List(opts v1.ListOptions) (result *v1alpha1.S2iRunList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewListAction(s2irunsResource, s2irunsKind, c.ns, opts), &v1alpha1.S2iRunList{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.S2iRunList{ListMeta: obj.(*v1alpha1.S2iRunList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.S2iRunList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested s2iRuns.
|
||||
func (c *FakeS2iRuns) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewWatchAction(s2irunsResource, c.ns, opts))
|
||||
|
||||
}
|
||||
|
||||
// Create takes the representation of a s2iRun and creates it. Returns the server's representation of the s2iRun, and an error, if there is any.
|
||||
func (c *FakeS2iRuns) Create(s2iRun *v1alpha1.S2iRun) (result *v1alpha1.S2iRun, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewCreateAction(s2irunsResource, c.ns, s2iRun), &v1alpha1.S2iRun{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iRun), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a s2iRun and updates it. Returns the server's representation of the s2iRun, and an error, if there is any.
|
||||
func (c *FakeS2iRuns) Update(s2iRun *v1alpha1.S2iRun) (result *v1alpha1.S2iRun, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateAction(s2irunsResource, c.ns, s2iRun), &v1alpha1.S2iRun{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iRun), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeS2iRuns) UpdateStatus(s2iRun *v1alpha1.S2iRun) (*v1alpha1.S2iRun, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewUpdateSubresourceAction(s2irunsResource, "status", c.ns, s2iRun), &v1alpha1.S2iRun{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iRun), err
|
||||
}
|
||||
|
||||
// Delete takes name of the s2iRun and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeS2iRuns) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewDeleteAction(s2irunsResource, c.ns, name), &v1alpha1.S2iRun{})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeS2iRuns) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewDeleteCollectionAction(s2irunsResource, c.ns, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.S2iRunList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched s2iRun.
|
||||
func (c *FakeS2iRuns) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.S2iRun, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewPatchSubresourceAction(s2irunsResource, c.ns, name, pt, data, subresources...), &v1alpha1.S2iRun{})
|
||||
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.S2iRun), err
|
||||
}
|
||||
@@ -19,3 +19,9 @@ limitations under the License.
|
||||
package v1alpha1
|
||||
|
||||
type S2iBinaryExpansion interface{}
|
||||
|
||||
type S2iBuilderExpansion interface{}
|
||||
|
||||
type S2iBuilderTemplateExpansion interface{}
|
||||
|
||||
type S2iRunExpansion interface{}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,6 +13,7 @@ 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
|
||||
@@ -20,12 +21,12 @@ package v1alpha1
|
||||
import (
|
||||
"time"
|
||||
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
scheme "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
|
||||
)
|
||||
|
||||
// S2iBuildersGetter has a method to return a S2iBuilderInterface.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,6 +13,7 @@ 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
|
||||
@@ -20,12 +21,12 @@ package v1alpha1
|
||||
import (
|
||||
"time"
|
||||
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
scheme "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
|
||||
)
|
||||
|
||||
// S2iBuilderTemplatesGetter has a method to return a S2iBuilderTemplateInterface.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,6 +13,7 @@ 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
|
||||
@@ -20,12 +21,12 @@ package v1alpha1
|
||||
import (
|
||||
"time"
|
||||
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
scheme "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
|
||||
)
|
||||
|
||||
// S2iRunsGetter has a method to return a S2iRunInterface.
|
||||
@@ -26,6 +26,12 @@ import (
|
||||
type Interface interface {
|
||||
// S2iBinaries returns a S2iBinaryInformer.
|
||||
S2iBinaries() S2iBinaryInformer
|
||||
// S2iBuilders returns a S2iBuilderInformer.
|
||||
S2iBuilders() S2iBuilderInformer
|
||||
// S2iBuilderTemplates returns a S2iBuilderTemplateInformer.
|
||||
S2iBuilderTemplates() S2iBuilderTemplateInformer
|
||||
// S2iRuns returns a S2iRunInformer.
|
||||
S2iRuns() S2iRunInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
@@ -43,3 +49,18 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList
|
||||
func (v *version) S2iBinaries() S2iBinaryInformer {
|
||||
return &s2iBinaryInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
// S2iBuilders returns a S2iBuilderInformer.
|
||||
func (v *version) S2iBuilders() S2iBuilderInformer {
|
||||
return &s2iBuilderInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
// S2iBuilderTemplates returns a S2iBuilderTemplateInformer.
|
||||
func (v *version) S2iBuilderTemplates() S2iBuilderTemplateInformer {
|
||||
return &s2iBuilderTemplateInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
// S2iRuns returns a S2iRunInformer.
|
||||
func (v *version) S2iRuns() S2iRunInformer {
|
||||
return &s2iRunInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,6 +13,7 @@ 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 informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
@@ -20,14 +21,14 @@ package v1alpha1
|
||||
import (
|
||||
time "time"
|
||||
|
||||
devopsv1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
versioned "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/client/listers/devops/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// S2iBuilderInformer provides access to a shared informer and lister for
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,6 +13,7 @@ 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 informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
@@ -20,14 +21,14 @@ package v1alpha1
|
||||
import (
|
||||
time "time"
|
||||
|
||||
devopsv1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
versioned "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/client/listers/devops/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// S2iBuilderTemplateInformer provides access to a shared informer and lister for
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,6 +13,7 @@ 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 informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
@@ -20,14 +21,14 @@ package v1alpha1
|
||||
import (
|
||||
time "time"
|
||||
|
||||
devopsv1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
versioned "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/client/listers/devops/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/client/listers/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// S2iRunInformer provides access to a shared informer and lister for
|
||||
@@ -58,6 +58,12 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
|
||||
// Group=devops.kubesphere.io, Version=v1alpha1
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("s2ibinaries"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iBinaries().Informer()}, nil
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("s2ibuilders"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iBuilders().Informer()}, nil
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("s2ibuildertemplates"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iBuilderTemplates().Informer()}, nil
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("s2iruns"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iRuns().Informer()}, nil
|
||||
|
||||
// Group=network.kubesphere.io, Version=v1alpha1
|
||||
case networkv1alpha1.SchemeGroupVersion.WithResource("namespacenetworkpolicies"):
|
||||
|
||||
@@ -25,3 +25,23 @@ type S2iBinaryListerExpansion interface{}
|
||||
// S2iBinaryNamespaceListerExpansion allows custom methods to be added to
|
||||
// S2iBinaryNamespaceLister.
|
||||
type S2iBinaryNamespaceListerExpansion interface{}
|
||||
|
||||
// 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{}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,15 +13,16 @@ 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
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// S2iBuilderLister helps list S2iBuilders.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,15 +13,16 @@ 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
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// S2iBuilderTemplateLister helps list S2iBuilderTemplates.
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
Copyright 2019 The Kubesphere Authors.
|
||||
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.
|
||||
@@ -13,15 +13,16 @@ 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
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
// S2iRunLister helps list S2iRuns.
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
|
||||
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 controller
|
||||
|
||||
import "kubesphere.io/kubesphere/pkg/controller/clusterrolebinding"
|
||||
|
||||
func init() {
|
||||
// AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
|
||||
AddToManagerFuncs = append(AddToManagerFuncs, clusterrolebinding.Add)
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
|
||||
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 controller
|
||||
|
||||
import "kubesphere.io/kubesphere/pkg/controller/namespace"
|
||||
|
||||
func init() {
|
||||
// AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
|
||||
AddToManagerFuncs = append(AddToManagerFuncs, namespace.Add)
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
/*
|
||||
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 controller
|
||||
|
||||
import (
|
||||
"github.com/kubernetes-sigs/application/pkg/controller/application"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Add application to manager functions
|
||||
AddToManagerFuncs = append(AddToManagerFuncs, application.Add)
|
||||
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
|
||||
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 controller
|
||||
|
||||
import "kubesphere.io/kubesphere/pkg/controller/workspace"
|
||||
|
||||
func init() {
|
||||
// AddToManagerFuncs is a list of functions to create controllers and add them to a manager.
|
||||
AddToManagerFuncs = append(AddToManagerFuncs, workspace.Add)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/*
|
||||
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 controller
|
||||
|
||||
import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
)
|
||||
|
||||
// AddToManagerFuncs is a list of functions to add all Controllers to the Manager
|
||||
var AddToManagerFuncs []func(manager.Manager) error
|
||||
|
||||
// AddToManager adds all Controllers to the Manager
|
||||
func AddToManager(m manager.Manager) error {
|
||||
for _, f := range AddToManagerFuncs {
|
||||
if err := f(m); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -69,13 +69,17 @@ var (
|
||||
|
||||
// Add creates a new Namespace Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller
|
||||
// and Start it when the Manager is Started.
|
||||
func Add(mgr manager.Manager) error {
|
||||
return add(mgr, newReconciler(mgr))
|
||||
func Add(mgr manager.Manager, openpitrixClient openpitrix.Client) error {
|
||||
return add(mgr, newReconciler(mgr, openpitrixClient))
|
||||
}
|
||||
|
||||
// newReconciler returns a new reconcile.Reconciler
|
||||
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
|
||||
return &ReconcileNamespace{Client: mgr.GetClient(), scheme: mgr.GetScheme()}
|
||||
func newReconciler(mgr manager.Manager, openpitrixClient openpitrix.Client) reconcile.Reconciler {
|
||||
return &ReconcileNamespace{
|
||||
Client: mgr.GetClient(),
|
||||
scheme: mgr.GetScheme(),
|
||||
openpitrixClient: openpitrixClient,
|
||||
}
|
||||
}
|
||||
|
||||
// add adds a new Controller to mgr with r as the reconcile.Reconciler
|
||||
|
||||
@@ -18,26 +18,21 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"time"
|
||||
|
||||
s2iv1alpha1 "github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
s2iclient "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
s2iinformers "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions/devops/v1alpha1"
|
||||
s2ilisters "github.com/kubesphere/s2ioperator/pkg/client/listers/devops/v1alpha1"
|
||||
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
devopsclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
devopsinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops/v1alpha1"
|
||||
devopslisters "kubesphere.io/kubesphere/pkg/client/listers/devops/v1alpha1"
|
||||
)
|
||||
|
||||
type S2iRunController struct {
|
||||
client clientset.Interface
|
||||
s2iClient s2iclient.Interface
|
||||
type Controller struct {
|
||||
client clientset.Interface
|
||||
|
||||
devopsClient devopsclient.Interface
|
||||
|
||||
eventBroadcaster record.EventBroadcaster
|
||||
eventRecorder record.EventRecorder
|
||||
|
||||
s2iRunLister s2ilisters.S2iRunLister
|
||||
s2iRunLister devopslisters.S2iRunLister
|
||||
s2iRunSynced cache.InformerSynced
|
||||
|
||||
s2iBinaryLister devopslisters.S2iBinaryLister
|
||||
@@ -48,9 +43,10 @@ type S2iRunController struct {
|
||||
workerLoopPeriod time.Duration
|
||||
}
|
||||
|
||||
func NewController(devopsclientset devopsclient.Interface, s2iclientset s2iclient.Interface,
|
||||
func NewS2iRunController(devopsClientSet devopsclient.Interface,
|
||||
client clientset.Interface,
|
||||
s2ibinInformer devopsinformers.S2iBinaryInformer, s2iRunInformer s2iinformers.S2iRunInformer) *S2iRunController {
|
||||
s2iBinInformer devopsinformers.S2iBinaryInformer,
|
||||
s2iRunInformer devopsinformers.S2iRunInformer) *Controller {
|
||||
|
||||
broadcaster := record.NewBroadcaster()
|
||||
broadcaster.StartLogging(func(format string, args ...interface{}) {
|
||||
@@ -59,13 +55,12 @@ func NewController(devopsclientset devopsclient.Interface, s2iclientset s2iclien
|
||||
broadcaster.StartRecordingToSink(&v1core.EventSinkImpl{Interface: client.CoreV1().Events("")})
|
||||
recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "s2irun-controller"})
|
||||
|
||||
v := &S2iRunController{
|
||||
v := &Controller{
|
||||
client: client,
|
||||
devopsClient: devopsclientset,
|
||||
s2iClient: s2iclientset,
|
||||
devopsClient: devopsClientSet,
|
||||
workqueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "s2irun"),
|
||||
s2iBinaryLister: s2ibinInformer.Lister(),
|
||||
s2iBinarySynced: s2ibinInformer.Informer().HasSynced,
|
||||
s2iBinaryLister: s2iBinInformer.Lister(),
|
||||
s2iBinarySynced: s2iBinInformer.Informer().HasSynced,
|
||||
s2iRunLister: s2iRunInformer.Lister(),
|
||||
s2iRunSynced: s2iRunInformer.Informer().HasSynced,
|
||||
workerLoopPeriod: time.Second,
|
||||
@@ -77,8 +72,8 @@ func NewController(devopsclientset devopsclient.Interface, s2iclientset s2iclien
|
||||
s2iRunInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: v.enqueueS2iRun,
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
old := oldObj.(*s2iv1alpha1.S2iRun)
|
||||
new := newObj.(*s2iv1alpha1.S2iRun)
|
||||
old := oldObj.(*devopsv1alpha1.S2iRun)
|
||||
new := newObj.(*devopsv1alpha1.S2iRun)
|
||||
if old.ResourceVersion == new.ResourceVersion {
|
||||
return
|
||||
}
|
||||
@@ -92,7 +87,7 @@ func NewController(devopsclientset devopsclient.Interface, s2iclientset s2iclien
|
||||
// enqueueFoo takes a Foo resource and converts it into a namespace/name
|
||||
// string which is then put onto the work workqueue. This method should *not* be
|
||||
// passed resources of any type other than Foo.
|
||||
func (c *S2iRunController) enqueueS2iRun(obj interface{}) {
|
||||
func (c Controller) enqueueS2iRun(obj interface{}) {
|
||||
var key string
|
||||
var err error
|
||||
if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil {
|
||||
@@ -102,7 +97,7 @@ func (c *S2iRunController) enqueueS2iRun(obj interface{}) {
|
||||
c.workqueue.Add(key)
|
||||
}
|
||||
|
||||
func (c *S2iRunController) processNextWorkItem() bool {
|
||||
func (c Controller) processNextWorkItem() bool {
|
||||
obj, shutdown := c.workqueue.Get()
|
||||
|
||||
if shutdown {
|
||||
@@ -136,17 +131,17 @@ func (c *S2iRunController) processNextWorkItem() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *S2iRunController) worker() {
|
||||
func (c Controller) worker() {
|
||||
|
||||
for c.processNextWorkItem() {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *S2iRunController) Start(stopCh <-chan struct{}) error {
|
||||
func (c Controller) Start(stopCh <-chan struct{}) error {
|
||||
return c.Run(1, stopCh)
|
||||
}
|
||||
|
||||
func (c *S2iRunController) Run(workers int, stopCh <-chan struct{}) error {
|
||||
func (c Controller) Run(workers int, stopCh <-chan struct{}) error {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.workqueue.ShutDown()
|
||||
|
||||
@@ -168,7 +163,7 @@ func (c *S2iRunController) Run(workers int, stopCh <-chan struct{}) error {
|
||||
// syncHandler compares the actual state with the desired, and attempts to
|
||||
// converge the two. It then updates the Status block of the Foo resource
|
||||
// with the current status of the resource.
|
||||
func (c *S2iRunController) syncHandler(key string) error {
|
||||
func (c Controller) syncHandler(key string) error {
|
||||
namespace, name, err := cache.SplitMetaNamespaceKey(key)
|
||||
if err != nil {
|
||||
klog.Error(err, fmt.Sprintf("could not split s2irun meta %s ", key))
|
||||
@@ -189,7 +184,7 @@ func (c *S2iRunController) syncHandler(key string) error {
|
||||
if s2irun.ObjectMeta.DeletionTimestamp.IsZero() {
|
||||
if !sliceutil.HasString(s2irun.ObjectMeta.Finalizers, devopsv1alpha1.S2iBinaryFinalizerName) {
|
||||
s2irun.ObjectMeta.Finalizers = append(s2irun.ObjectMeta.Finalizers, devopsv1alpha1.S2iBinaryFinalizerName)
|
||||
_, err := c.s2iClient.DevopsV1alpha1().S2iRuns(namespace).Update(s2irun)
|
||||
_, err = c.devopsClient.DevopsV1alpha1().S2iRuns(namespace).Update(s2irun)
|
||||
if err != nil {
|
||||
klog.Error(err, fmt.Sprintf("failed to update s2irun %s", key))
|
||||
return err
|
||||
@@ -205,7 +200,7 @@ func (c *S2iRunController) syncHandler(key string) error {
|
||||
s2irun.ObjectMeta.Finalizers = sliceutil.RemoveString(s2irun.ObjectMeta.Finalizers, func(item string) bool {
|
||||
return item == devopsv1alpha1.S2iBinaryFinalizerName
|
||||
})
|
||||
_, err := c.s2iClient.DevopsV1alpha1().S2iRuns(namespace).Update(s2irun)
|
||||
_, err = c.devopsClient.DevopsV1alpha1().S2iRuns(namespace).Update(s2irun)
|
||||
if err != nil {
|
||||
klog.Error(err, fmt.Sprintf("failed to update s2irun %s ", key))
|
||||
return err
|
||||
@@ -218,7 +213,7 @@ func (c *S2iRunController) syncHandler(key string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *S2iRunController) DeleteS2iBinary(s2irun *s2iv1alpha1.S2iRun) error {
|
||||
func (c Controller) DeleteS2iBinary(s2irun *devopsv1alpha1.S2iRun) error {
|
||||
s2iBinName := s2irun.Labels[devopsv1alpha1.S2iBinaryLabelKey]
|
||||
s2iBin, err := c.s2iBinaryLister.S2iBinaries(s2irun.Namespace).Get(s2iBinName)
|
||||
if err != nil {
|
||||
@@ -246,7 +241,7 @@ func (c *S2iRunController) DeleteS2iBinary(s2irun *s2iv1alpha1.S2iRun) error {
|
||||
}
|
||||
|
||||
// cleanOtherS2iBinary clean up s2ibinary created for more than 24 hours without associated s2irun
|
||||
func (c *S2iRunController) cleanOtherS2iBinary(namespace string) error {
|
||||
func (c Controller) cleanOtherS2iBinary(namespace string) error {
|
||||
s2iBins, err := c.s2iBinaryLister.S2iBinaries(namespace).List(nil)
|
||||
if err != nil {
|
||||
klog.Error(err, fmt.Sprintf("failed to list s2ibin in %s ", namespace))
|
||||
|
||||
@@ -29,10 +29,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/record"
|
||||
log "k8s.io/klog"
|
||||
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
cs "kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"reflect"
|
||||
@@ -42,7 +42,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/handler"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/source"
|
||||
"sync"
|
||||
)
|
||||
@@ -53,23 +52,16 @@ const (
|
||||
workspaceViewerDescription = "Allows viewer access to view all resources in the workspace."
|
||||
)
|
||||
|
||||
var log = logf.Log.WithName("workspace-controller")
|
||||
|
||||
/**
|
||||
* USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller
|
||||
* business logic. Delete these comments after modifying this file.*
|
||||
*/
|
||||
|
||||
// Add creates a new Workspace Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller
|
||||
// and Start it when the Manager is Started.
|
||||
func Add(mgr manager.Manager) error {
|
||||
return add(mgr, newReconciler(mgr))
|
||||
func Add(mgr manager.Manager, kubesphereClient kubesphere.Interface) error {
|
||||
return add(mgr, newReconciler(mgr, kubesphereClient))
|
||||
}
|
||||
|
||||
// newReconciler returns a new reconcile.Reconciler
|
||||
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
|
||||
func newReconciler(mgr manager.Manager, kubesphereClient kubesphere.Interface) reconcile.Reconciler {
|
||||
return &ReconcileWorkspace{Client: mgr.GetClient(), scheme: mgr.GetScheme(),
|
||||
recorder: mgr.GetEventRecorderFor("workspace-controller"), ksclient: cs.ClientSets().KubeSphere()}
|
||||
recorder: mgr.GetEventRecorderFor("workspace-controller"), ksclient: kubesphereClient}
|
||||
}
|
||||
|
||||
// add adds a new Controller to mgr with r as the reconcile.Reconciler
|
||||
@@ -328,7 +320,6 @@ func (r *ReconcileWorkspace) deleteDevOpsProjects(instance *tenantv1alpha1.Works
|
||||
|
||||
log.Info("Delete DevOps Projects")
|
||||
for {
|
||||
errChan := make(chan error, 10)
|
||||
projects, err := r.ksclient.ListWorkspaceDevOpsProjects(instance.Name)
|
||||
if err != nil {
|
||||
log.Error(err, "Failed to Get Workspace's DevOps Projects", "ws", instance.Name)
|
||||
@@ -337,10 +328,11 @@ func (r *ReconcileWorkspace) deleteDevOpsProjects(instance *tenantv1alpha1.Works
|
||||
if projects.TotalCount == 0 {
|
||||
return nil
|
||||
}
|
||||
errChan := make(chan error, len(projects.Items))
|
||||
for _, project := range projects.Items {
|
||||
wg.Add(1)
|
||||
go func(workspace, devops string) {
|
||||
err := r.ksclient.DeleteWorkspaceDevOpsProjects(workspace, devops)
|
||||
err = r.ksclient.DeleteWorkspaceDevOpsProjects(workspace, devops)
|
||||
errChan <- err
|
||||
wg.Done()
|
||||
}(instance.Name, project.ProjectId)
|
||||
|
||||
@@ -20,8 +20,8 @@ package informers
|
||||
import (
|
||||
applicationclient "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned"
|
||||
applicationinformers "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
|
||||
s2i "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
s2iinformers "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
|
||||
istioclient "istio.io/client-go/pkg/clientset/versioned"
|
||||
istioinformers "istio.io/client-go/pkg/informers/externalversions"
|
||||
k8sinformers "k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||
@@ -33,19 +33,22 @@ const defaultResync = 600 * time.Second
|
||||
|
||||
type InformerFactory interface {
|
||||
KubernetesSharedInformerFactory() k8sinformers.SharedInformerFactory
|
||||
S2iSharedInformerFactory() s2iinformers.SharedInformerFactory
|
||||
KubeSphereSharedInformerFactory() ksinformers.SharedInformerFactory
|
||||
IstioSharedInformerFactory() istioinformers.SharedInformerFactory
|
||||
ApplicationSharedInformerFactory() applicationinformers.SharedInformerFactory
|
||||
|
||||
// Start all the informer factories if not nil
|
||||
Start(stopCh <-chan struct{})
|
||||
}
|
||||
|
||||
type informerFactories struct {
|
||||
informerFactory k8sinformers.SharedInformerFactory
|
||||
s2iInformerFactory s2iinformers.SharedInformerFactory
|
||||
ksInformerFactory ksinformers.SharedInformerFactory
|
||||
appInformerFactory applicationinformers.SharedInformerFactory
|
||||
informerFactory k8sinformers.SharedInformerFactory
|
||||
ksInformerFactory ksinformers.SharedInformerFactory
|
||||
istioInformerFactory istioinformers.SharedInformerFactory
|
||||
appInformerFactory applicationinformers.SharedInformerFactory
|
||||
}
|
||||
|
||||
func NewInformerFactories(client kubernetes.Interface, ksClient versioned.Interface, s2iClient s2i.Interface, appClient applicationclient.Interface) InformerFactory {
|
||||
func NewInformerFactories(client kubernetes.Interface, ksClient versioned.Interface, istioClient istioclient.Interface, appClient applicationclient.Interface) InformerFactory {
|
||||
factory := &informerFactories{}
|
||||
|
||||
if client != nil {
|
||||
@@ -56,14 +59,14 @@ func NewInformerFactories(client kubernetes.Interface, ksClient versioned.Interf
|
||||
factory.ksInformerFactory = ksinformers.NewSharedInformerFactory(ksClient, defaultResync)
|
||||
}
|
||||
|
||||
if s2iClient != nil {
|
||||
factory.s2iInformerFactory = s2iinformers.NewSharedInformerFactory(s2iClient, defaultResync)
|
||||
}
|
||||
|
||||
if appClient != nil {
|
||||
factory.appInformerFactory = applicationinformers.NewSharedInformerFactory(appClient, defaultResync)
|
||||
}
|
||||
|
||||
if istioClient != nil {
|
||||
factory.istioInformerFactory = istioinformers.NewSharedInformerFactory(istioClient, defaultResync)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
@@ -71,10 +74,6 @@ func (f *informerFactories) KubernetesSharedInformerFactory() k8sinformers.Share
|
||||
return f.informerFactory
|
||||
}
|
||||
|
||||
func (f *informerFactories) S2iSharedInformerFactory() s2iinformers.SharedInformerFactory {
|
||||
return f.s2iInformerFactory
|
||||
}
|
||||
|
||||
func (f *informerFactories) KubeSphereSharedInformerFactory() ksinformers.SharedInformerFactory {
|
||||
return f.ksInformerFactory
|
||||
}
|
||||
@@ -82,3 +81,25 @@ func (f *informerFactories) KubeSphereSharedInformerFactory() ksinformers.Shared
|
||||
func (f *informerFactories) ApplicationSharedInformerFactory() applicationinformers.SharedInformerFactory {
|
||||
return f.appInformerFactory
|
||||
}
|
||||
|
||||
func (f *informerFactories) IstioSharedInformerFactory() istioinformers.SharedInformerFactory {
|
||||
return f.istioInformerFactory
|
||||
}
|
||||
|
||||
func (f *informerFactories) Start(stopCh <-chan struct{}) {
|
||||
if f.informerFactory != nil {
|
||||
f.informerFactory.Start(stopCh)
|
||||
}
|
||||
|
||||
if f.ksInformerFactory != nil {
|
||||
f.ksInformerFactory.Start(stopCh)
|
||||
}
|
||||
|
||||
if f.informerFactory != nil {
|
||||
f.istioInformerFactory.Start(stopCh)
|
||||
}
|
||||
|
||||
if f.appInformerFactory != nil {
|
||||
f.appInformerFactory.Start(stopCh)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
func addWebService(c *restful.Container, devopsClient devops.Interface,
|
||||
func AddToContainer(c *restful.Container, devopsClient devops.Interface,
|
||||
dbClient *mysql.Database, sonarClient sonarqube.SonarInterface, ksClient versioned.Interface,
|
||||
ksInformer externalversions.SharedInformerFactory, s3Client s3.Interface) error {
|
||||
|
||||
|
||||
@@ -17,11 +17,18 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
apierr "kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"kubesphere.io/kubesphere/pkg/utils/iputil"
|
||||
"kubesphere.io/kubesphere/pkg/utils/jwtutil"
|
||||
"net/http"
|
||||
|
||||
iamapi "kubesphere.io/kubesphere/pkg/api/iam"
|
||||
)
|
||||
|
||||
const (
|
||||
kindTokenReview = "TokenReview"
|
||||
)
|
||||
|
||||
type iamHandler struct {
|
||||
@@ -29,11 +36,10 @@ type iamHandler struct {
|
||||
imOperator iam.IdentityManagementInterface
|
||||
}
|
||||
|
||||
func newIAMHandler(k8sClient k8s.Client, ldapClient ldappool.Client, options iam.Config) *iamHandler {
|
||||
factory := informers.NewInformerFactories(k8sClient.Kubernetes(), k8sClient.KubeSphere(), k8sClient.S2i(), k8sClient.Application())
|
||||
func newIAMHandler(k8sClient k8s.Client, factory informers.InformerFactory, ldapClient ldappool.Interface, cacheClient cache.Interface, options *iamapi.AuthenticationOptions) *iamHandler {
|
||||
return &iamHandler{
|
||||
amOperator: iam.NewAMOperator(factory.KubernetesSharedInformerFactory()),
|
||||
imOperator: iam.NewIMOperator(ldapClient, options),
|
||||
amOperator: iam.NewAMOperator(k8sClient.Kubernetes(), factory.KubernetesSharedInformerFactory()),
|
||||
imOperator: iam.NewIMOperator(ldapClient, cacheClient, options),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +66,7 @@ func (h *iamHandler) TokenReviewHandler(req *restful.Request, resp *restful.Resp
|
||||
|
||||
if err != nil {
|
||||
failed := iamv1alpha2.TokenReview{APIVersion: tokenReview.APIVersion,
|
||||
Kind: iam.KindTokenReview,
|
||||
Kind: kindTokenReview,
|
||||
Status: &iamv1alpha2.Status{
|
||||
Authenticated: false,
|
||||
},
|
||||
@@ -92,7 +98,7 @@ func (h *iamHandler) TokenReviewHandler(req *restful.Request, resp *restful.Resp
|
||||
}
|
||||
|
||||
success := iamv1alpha2.TokenReview{APIVersion: tokenReview.APIVersion,
|
||||
Kind: iam.KindTokenReview,
|
||||
Kind: kindTokenReview,
|
||||
Status: &iamv1alpha2.Status{
|
||||
Authenticated: true,
|
||||
User: map[string]interface{}{"username": user.Username, "uid": user.Username, "groups": user.Groups},
|
||||
@@ -378,7 +384,7 @@ func (h *iamHandler) ListRoleUsers(req *restful.Request, resp *restful.Response)
|
||||
api.HandleInternalError(resp, err)
|
||||
return
|
||||
}
|
||||
result := make([]*iam.User, 0)
|
||||
result := make([]*iamapi.User, 0)
|
||||
for _, roleBinding := range roleBindings {
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind {
|
||||
@@ -413,7 +419,7 @@ func (h *iamHandler) ListNamespaceUsers(req *restful.Request, resp *restful.Resp
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]*iam.User, 0)
|
||||
result := make([]*iamapi.User, 0)
|
||||
for _, roleBinding := range roleBindings {
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind {
|
||||
@@ -445,7 +451,7 @@ func (h *iamHandler) ListClusterRoleUsers(req *restful.Request, resp *restful.Re
|
||||
return
|
||||
}
|
||||
|
||||
result := make([]*iam.User, 0)
|
||||
result := make([]*iamapi.User, 0)
|
||||
for _, roleBinding := range clusterRoleBindings {
|
||||
for _, subject := range roleBinding.Subjects {
|
||||
if subject.Kind == rbacv1.UserKind {
|
||||
|
||||
@@ -23,26 +23,28 @@ import (
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
iamv1alpha2 "kubesphere.io/kubesphere/pkg/api/iam/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/policy"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const GroupName = "iam.kubesphere.io"
|
||||
const groupName = "iam.kubesphere.io"
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
var GroupVersion = schema.GroupVersion{Group: groupName, Version: "v1alpha2"}
|
||||
|
||||
func AddToContainer(c *restful.Container, k8sClient k8s.Client, ldapClient ldappool.Client, options iam.Config) error {
|
||||
func AddToContainer(c *restful.Container, k8sClient k8s.Client, factory informers.InformerFactory, ldapClient ldappool.Interface, cacheClient cache.Interface, options *iam.AuthenticationOptions) error {
|
||||
ws := runtime.NewWebService(GroupVersion)
|
||||
|
||||
handler := newIAMHandler(k8sClient, ldapClient, options)
|
||||
handler := newIAMHandler(k8sClient, factory, ldapClient, cacheClient, options)
|
||||
|
||||
ws.Route(ws.POST("/authenticate").
|
||||
To(handler.TokenReviewHandler).
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package kapis
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
devopsv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/devops/v1alpha2"
|
||||
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"
|
||||
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
|
||||
tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
|
||||
terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
ldappool "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/mysql"
|
||||
op "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||
)
|
||||
|
||||
func InstallAPIs(container *restful.Container, client k8s.Client, op op.Client, db *mysql.Database, logging logging.Interface, monitoring monitoring.Interface) {
|
||||
urlruntime.Must(servicemeshv1alpha2.AddToContainer(container))
|
||||
urlruntime.Must(devopsv1alpha2.AddToContainer(container))
|
||||
urlruntime.Must(loggingv1alpha2.AddToContainer(container, client, logging))
|
||||
urlruntime.Must(monitoringv1alpha2.AddToContainer(container, client, monitoring))
|
||||
urlruntime.Must(openpitrixv1.AddToContainer(container, client, op))
|
||||
urlruntime.Must(operationsv1alpha2.AddToContainer(container, client))
|
||||
urlruntime.Must(resourcesv1alpha2.AddToContainer(container, client))
|
||||
urlruntime.Must(tenantv1alpha2.AddToContainer(container, client, db))
|
||||
urlruntime.Must(terminalv1alpha2.AddToContainer(container, client))
|
||||
}
|
||||
|
||||
func InstallAuthorizationAPIs(container *restful.Container, k8sClient k8s.Client, ldapClient ldappool.Client, imOptions iam.Config) {
|
||||
urlruntime.Must(iamv1alpha2.AddToContainer(container, k8sClient, ldapClient, imOptions))
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/models/openpitrix"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
op "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -25,9 +24,7 @@ type openpitrixHandler struct {
|
||||
informers k8sinformers.SharedInformerFactory
|
||||
}
|
||||
|
||||
func newOpenpitrixHandler(k8sClient k8s.Client, opClient op.Client) *openpitrixHandler {
|
||||
|
||||
factory := informers.NewInformerFactories(k8sClient.Kubernetes(), k8sClient.KubeSphere(), k8sClient.S2i(), k8sClient.Application())
|
||||
func newOpenpitrixHandler(factory informers.InformerFactory, opClient op.Client) *openpitrixHandler {
|
||||
|
||||
return &openpitrixHandler{
|
||||
openpitrix: openpitrix.NewOpenpitrixOperator(factory.KubernetesSharedInformerFactory(), opClient),
|
||||
|
||||
@@ -24,11 +24,11 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
openpitrix2 "kubesphere.io/kubesphere/pkg/models/openpitrix"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
op "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||
"net/http"
|
||||
)
|
||||
@@ -39,11 +39,11 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"}
|
||||
|
||||
func AddToContainer(c *restful.Container, k8s k8s.Client, op op.Client) error {
|
||||
func AddToContainer(c *restful.Container, factory informers.InformerFactory, op op.Client) error {
|
||||
|
||||
mimePatch := []string{restful.MIME_JSON, runtime.MimeMergePatchJson, runtime.MimeJsonPatchJson}
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
handler := newOpenpitrixHandler(k8s, op)
|
||||
handler := newOpenpitrixHandler(factory, op)
|
||||
|
||||
webservice.Route(webservice.GET("/applications").
|
||||
To(handler.ListApplications).
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"fmt"
|
||||
"github.com/emicklei/go-restful"
|
||||
k8serr "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"kubesphere.io/kubesphere/pkg/models/workloads"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -14,9 +14,9 @@ type operationHandler struct {
|
||||
jobRunner workloads.JobRunner
|
||||
}
|
||||
|
||||
func newOperationHandler(client k8s.Client) *operationHandler {
|
||||
func newOperationHandler(client kubernetes.Interface) *operationHandler {
|
||||
return &operationHandler{
|
||||
jobRunner: workloads.NewJobRunner(client.Kubernetes()),
|
||||
jobRunner: workloads.NewJobRunner(client),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,10 @@ package v1alpha2
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -33,7 +33,7 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
func AddToContainer(c *restful.Container, client k8s.Client) error {
|
||||
func AddToContainer(c *restful.Container, client kubernetes.Interface) error {
|
||||
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/emicklei/go-restful"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
k8serr "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
@@ -20,7 +21,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/models/routers"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -38,20 +38,18 @@ type resourceHandler struct {
|
||||
kubectlOperator kubectl.Interface
|
||||
}
|
||||
|
||||
func newResourceHandler(client k8s.Client) *resourceHandler {
|
||||
|
||||
factory := informers.NewInformerFactories(client.Kubernetes(), client.KubeSphere(), client.S2i(), client.Application())
|
||||
func newResourceHandler(client kubernetes.Interface, factory informers.InformerFactory) *resourceHandler {
|
||||
|
||||
return &resourceHandler{
|
||||
resourcesGetter: resource.NewResourceGetter(factory),
|
||||
componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()),
|
||||
resourceQuotaGetter: quotas.NewResourceQuotaGetter(factory.KubernetesSharedInformerFactory()),
|
||||
revisionGetter: revisions.NewRevisionGetter(factory.KubernetesSharedInformerFactory()),
|
||||
routerOperator: routers.NewRouterOperator(client.Kubernetes(), factory.KubernetesSharedInformerFactory()),
|
||||
routerOperator: routers.NewRouterOperator(client, factory.KubernetesSharedInformerFactory()),
|
||||
gitVerifier: git.NewGitVerifier(factory.KubernetesSharedInformerFactory()),
|
||||
registryGetter: registries.NewRegistryGetter(factory.KubernetesSharedInformerFactory()),
|
||||
kubeconfigOperator: kubeconfig.NewKubeconfigOperator(),
|
||||
kubectlOperator: kubectl.NewKubectlOperator(client.Kubernetes(), factory.KubernetesSharedInformerFactory()),
|
||||
kubectlOperator: kubectl.NewKubectlOperator(client, factory.KubernetesSharedInformerFactory()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,16 +23,17 @@ import (
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"kubesphere.io/kubesphere/pkg/api"
|
||||
"kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
gitmodel "kubesphere.io/kubesphere/pkg/models/git"
|
||||
registriesmodel "kubesphere.io/kubesphere/pkg/models/registries"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -42,9 +43,9 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
func AddToContainer(c *restful.Container, client k8s.Client) error {
|
||||
func AddToContainer(c *restful.Container, client kubernetes.Interface, factory informers.InformerFactory) error {
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
handler := newResourceHandler(client)
|
||||
handler := newResourceHandler(client, factory)
|
||||
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}").
|
||||
To(handler.handleListNamespaceResources).
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models/components"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha3/resource"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -16,9 +15,7 @@ type Handler struct {
|
||||
componentsGetter components.ComponentsGetter
|
||||
}
|
||||
|
||||
func New(client k8s.Client) *Handler {
|
||||
factory := informers.NewInformerFactories(client.Kubernetes(), client.KubeSphere(), client.S2i(), client.Application())
|
||||
|
||||
func New(factory informers.InformerFactory) *Handler {
|
||||
return &Handler{
|
||||
namespacedResourceGetter: resource.New(factory),
|
||||
componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()),
|
||||
|
||||
@@ -25,7 +25,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/query"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
@@ -40,10 +40,10 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
func AddWebService(c *restful.Container, client k8s.Client) error {
|
||||
func AddToContainer(c *restful.Container, informerFactory informers.InformerFactory) error {
|
||||
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
handler := New(client)
|
||||
handler := New(informerFactory)
|
||||
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}").
|
||||
To(handler.handleGetNamespacedResource).
|
||||
|
||||
@@ -28,12 +28,11 @@ type tenantHandler struct {
|
||||
am iam.AccessManagementInterface
|
||||
}
|
||||
|
||||
func newTenantHandler(k8sClient k8s.Client, db *mysql.Database) *tenantHandler {
|
||||
factory := informers.NewInformerFactories(k8sClient.Kubernetes(), k8sClient.KubeSphere(), k8sClient.S2i(), k8sClient.Application())
|
||||
func newTenantHandler(k8sClient k8s.Client, factory informers.InformerFactory, db *mysql.Database) *tenantHandler {
|
||||
|
||||
return &tenantHandler{
|
||||
tenant: tenant.New(k8sClient.Kubernetes(), factory.KubernetesSharedInformerFactory(), factory.KubeSphereSharedInformerFactory(), db),
|
||||
am: iam.NewAMOperator(factory.KubernetesSharedInformerFactory()),
|
||||
am: iam.NewAMOperator(k8sClient.Kubernetes(), factory.KubernetesSharedInformerFactory()),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/informers"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/policy"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
@@ -43,9 +44,9 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
func AddToContainer(c *restful.Container, k8sClient k8s.Client, db *mysql.Database) error {
|
||||
func AddToContainer(c *restful.Container, k8sClient k8s.Client, factory informers.InformerFactory, db *mysql.Database) error {
|
||||
ws := runtime.NewWebService(GroupVersion)
|
||||
handler := newTenantHandler(k8sClient, db)
|
||||
handler := newTenantHandler(k8sClient, factory, db)
|
||||
|
||||
ws.Route(ws.GET("/workspaces").
|
||||
To(handler.ListWorkspaces).
|
||||
|
||||
@@ -21,10 +21,11 @@ import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/emicklei/go-restful-openapi"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -33,11 +34,11 @@ const (
|
||||
|
||||
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
|
||||
|
||||
func AddToContainer(c *restful.Container, k8sClient k8s.Client) error {
|
||||
func AddToContainer(c *restful.Container, client kubernetes.Interface, config *rest.Config) error {
|
||||
|
||||
webservice := runtime.NewWebService(GroupVersion)
|
||||
|
||||
handler := newTerminalHandler(k8sClient.Kubernetes(), k8sClient.Config())
|
||||
handler := newTerminalHandler(client, config)
|
||||
|
||||
webservice.Route(webservice.GET("/namespaces/{namespace}/pods/{pod}").
|
||||
To(handler.handleTerminalSession).
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
@@ -33,7 +34,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/role"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||
)
|
||||
|
||||
@@ -62,8 +62,9 @@ type AccessManagementInterface interface {
|
||||
}
|
||||
|
||||
type amOperator struct {
|
||||
informers informers.SharedInformerFactory
|
||||
resources resource.ResourceGetter
|
||||
informers informers.SharedInformerFactory
|
||||
resources resource.ResourceGetter
|
||||
kubeClient kubernetes.Interface
|
||||
}
|
||||
|
||||
func (am *amOperator) ListClusterRoleBindings(clusterRole string) ([]*rbacv1.ClusterRoleBinding, error) {
|
||||
@@ -90,11 +91,15 @@ func (am *amOperator) UnBindAllRoles(username string) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func NewAMOperator(informers informers.SharedInformerFactory) *amOperator {
|
||||
func NewAMOperator(kubeClient kubernetes.Interface, informers informers.SharedInformerFactory) *amOperator {
|
||||
resourceGetter := resource.ResourceGetter{}
|
||||
resourceGetter.Add(v1alpha2.Role, role.NewRoleSearcher(informers))
|
||||
resourceGetter.Add(v1alpha2.ClusterRoles, clusterrole.NewClusterRoleSearcher(informers))
|
||||
return &amOperator{informers: informers, resources: resourceGetter}
|
||||
return &amOperator{
|
||||
informers: informers,
|
||||
resources: resourceGetter,
|
||||
kubeClient: kubeClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (am *amOperator) GetDevopsRoleSimpleRules(role string) []policy.SimpleRule {
|
||||
@@ -560,7 +565,7 @@ func (am *amOperator) CreateClusterRoleBinding(username string, clusterRoleName
|
||||
found, err := clusterRoleBindingLister.Get(username)
|
||||
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, err = client.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
|
||||
_, err = am.kubeClient.RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
|
||||
if err != nil {
|
||||
klog.Errorln("create cluster role binding", err)
|
||||
return err
|
||||
@@ -575,12 +580,12 @@ func (am *amOperator) CreateClusterRoleBinding(username string, clusterRoleName
|
||||
deletePolicy := metav1.DeletePropagationBackground
|
||||
gracePeriodSeconds := int64(0)
|
||||
deleteOption := &metav1.DeleteOptions{PropagationPolicy: &deletePolicy, GracePeriodSeconds: &gracePeriodSeconds}
|
||||
err = client.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Delete(found.Name, deleteOption)
|
||||
err = am.kubeClient.RbacV1().ClusterRoleBindings().Delete(found.Name, deleteOption)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
_, err = client.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
|
||||
_, err = am.kubeClient.RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
@@ -590,7 +595,7 @@ func (am *amOperator) CreateClusterRoleBinding(username string, clusterRoleName
|
||||
|
||||
if !ContainsUser(found.Subjects, username) {
|
||||
found.Subjects = clusterRoleBinding.Subjects
|
||||
_, err = client.ClientSets().K8s().Kubernetes().RbacV1().ClusterRoleBindings().Update(found)
|
||||
_, err = am.kubeClient.RbacV1().ClusterRoleBindings().Update(found)
|
||||
if err != nil {
|
||||
klog.Errorln("update cluster role binding", err)
|
||||
return err
|
||||
|
||||
@@ -20,216 +20,96 @@ package iam
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
"github.com/go-ldap/ldap"
|
||||
"github.com/go-redis/redis"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/oauth2"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"k8s.io/klog"
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
ldappool "kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"kubesphere.io/kubesphere/pkg/utils/jwtutil"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IdentityManagementInterface interface {
|
||||
CreateUser(user *User) (*User, error)
|
||||
CreateUser(user *iam.User) (*iam.User, error)
|
||||
DeleteUser(username string) error
|
||||
DescribeUser(username string) (*User, error)
|
||||
DescribeUser(username string) (*iam.User, error)
|
||||
Login(username, password, ip string) (*oauth2.Token, error)
|
||||
ModifyUser(user *User) (*User, error)
|
||||
ModifyUser(user *iam.User) (*iam.User, error)
|
||||
ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error)
|
||||
GetUserRoles(username string) ([]*rbacv1.Role, error)
|
||||
GetUserRole(namespace string, username string) (*rbacv1.Role, error)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
authRateLimit string
|
||||
maxAuthFailed int
|
||||
authTimeInterval time.Duration
|
||||
tokenIdleTimeout time.Duration
|
||||
enableMultiLogin bool
|
||||
}
|
||||
|
||||
type imOperator struct {
|
||||
config Config
|
||||
ldap ldappool.Client
|
||||
redis redis.Client
|
||||
authenticateOptions *iam.AuthenticationOptions
|
||||
ldapClient ldap.Interface
|
||||
cacheClient cache.Interface
|
||||
}
|
||||
|
||||
const (
|
||||
authRateLimitRegex = `(\d+)/(\d+[s|m|h])`
|
||||
defaultMaxAuthFailed = 5
|
||||
defaultAuthTimeInterval = 30 * time.Minute
|
||||
mailAttribute = "mail"
|
||||
uidAttribute = "uid"
|
||||
descriptionAttribute = "description"
|
||||
preferredLanguageAttribute = "preferredLanguage"
|
||||
createTimestampAttribute = "createTimestampAttribute"
|
||||
dateTimeLayout = "20060102150405Z"
|
||||
)
|
||||
|
||||
var (
|
||||
AuthRateLimitExceeded = errors.New("user auth rate limit exceeded")
|
||||
UserAlreadyExists = errors.New("user already exists")
|
||||
UserNotExists = errors.New("user not exists")
|
||||
)
|
||||
|
||||
func NewIMOperator(ldap ldappool.Client, config Config) *imOperator {
|
||||
imOperator := &imOperator{ldap: ldap, config: config}
|
||||
return imOperator
|
||||
func NewIMOperator(ldapClient ldap.Interface, cacheClient cache.Interface, options *iam.AuthenticationOptions) *imOperator {
|
||||
return &imOperator{ldapClient: ldapClient, cacheClient: cacheClient, authenticateOptions: options}
|
||||
|
||||
}
|
||||
|
||||
// TODO init in controller
|
||||
func (im *imOperator) Init() error {
|
||||
|
||||
userSearchBase := &ldap.AddRequest{
|
||||
DN: im.ldap.UserSearchBase(),
|
||||
Attributes: []ldap.Attribute{{
|
||||
Type: "objectClass",
|
||||
Vals: []string{"organizationalUnit", "top"},
|
||||
}, {
|
||||
Type: "ou",
|
||||
Vals: []string{"Users"},
|
||||
}},
|
||||
Controls: nil,
|
||||
}
|
||||
|
||||
err := im.createIfNotExists(userSearchBase)
|
||||
|
||||
func (im *imOperator) ModifyUser(user *iam.User) (*iam.User, error) {
|
||||
err := im.ldapClient.Update(user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
groupSearchBase := &ldap.AddRequest{
|
||||
DN: im.ldap.GroupSearchBase(),
|
||||
Attributes: []ldap.Attribute{{
|
||||
Type: "objectClass",
|
||||
Vals: []string{"organizationalUnit", "top"},
|
||||
}, {
|
||||
Type: "ou",
|
||||
Vals: []string{"Groups"},
|
||||
}},
|
||||
Controls: nil,
|
||||
}
|
||||
|
||||
err = im.createIfNotExists(groupSearchBase)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (im *imOperator) createIfNotExists(createRequest *ldap.AddRequest) error {
|
||||
conn, err := im.ldap.NewConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
createRequest.DN,
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
"(objectClass=*)",
|
||||
nil,
|
||||
nil,
|
||||
)
|
||||
|
||||
_, err = conn.Search(searchRequest)
|
||||
|
||||
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
|
||||
err = conn.Add(createRequest)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (im *imOperator) ModifyUser(user *User) (*User, error) {
|
||||
conn, err := im.ldap.NewConn()
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
dn := fmt.Sprintf("uid=%s,%s", user.Username, im.ldap.UserSearchBase())
|
||||
userModifyRequest := ldap.NewModifyRequest(dn, nil)
|
||||
|
||||
if user.Description != "" {
|
||||
userModifyRequest.Replace("description", []string{user.Description})
|
||||
}
|
||||
|
||||
if user.Lang != "" {
|
||||
userModifyRequest.Replace("preferredLanguage", []string{user.Lang})
|
||||
}
|
||||
|
||||
if user.Password != "" {
|
||||
userModifyRequest.Replace("userPassword", []string{user.Password})
|
||||
}
|
||||
|
||||
err = conn.Modify(userModifyRequest)
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// clear auth failed record
|
||||
if user.Password != "" {
|
||||
|
||||
records, err := im.redis.Keys(fmt.Sprintf("kubesphere:authfailed:%s:*", user.Username)).Result()
|
||||
|
||||
records, err := im.cacheClient.Keys(authenticationFailedKeyForUsername(user.Username, "*"))
|
||||
if err == nil {
|
||||
im.redis.Del(records...)
|
||||
im.cacheClient.Del(records...)
|
||||
}
|
||||
}
|
||||
|
||||
return im.DescribeUser(user.Username)
|
||||
return im.ldapClient.Get(user.Username)
|
||||
}
|
||||
|
||||
func authenticationFailedKeyForUsername(username, failedTimestamp string) string {
|
||||
return fmt.Sprintf("kubesphere:authfailed:%s:%s", username, failedTimestamp)
|
||||
}
|
||||
|
||||
func tokenKeyForUsername(username, token string) string {
|
||||
return fmt.Sprintf("kubesphere:users:%s:token:%s", username, token)
|
||||
}
|
||||
|
||||
func loginKeyForUsername(username, loginTimestamp, ip string) string {
|
||||
return fmt.Sprintf("kubesphere:users:%s:login-log:%s:%s", username, loginTimestamp, ip)
|
||||
}
|
||||
|
||||
func (im *imOperator) Login(username, password, ip string) (*oauth2.Token, error) {
|
||||
|
||||
records, err := im.redis.Keys(fmt.Sprintf("kubesphere:authfailed:%s:*", username)).Result()
|
||||
|
||||
records, err := im.cacheClient.Keys(authenticationFailedKeyForUsername(username, "*"))
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(records) >= im.config.maxAuthFailed {
|
||||
if len(records) >= im.authenticateOptions.MaxAuthenticateRetries {
|
||||
return nil, AuthRateLimitExceeded
|
||||
}
|
||||
|
||||
user, err := im.DescribeUser(username)
|
||||
|
||||
conn, err := im.ldap.NewConn()
|
||||
user, err := im.ldapClient.Get(username)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
dn := fmt.Sprintf("uid=%s,%s", user.Username, im.ldap.UserSearchBase())
|
||||
|
||||
// bind as the user to verify their password
|
||||
err = conn.Bind(dn, password)
|
||||
|
||||
err = im.ldapClient.Verify(user.Username, password)
|
||||
if err != nil {
|
||||
if ldap.IsErrorWithCode(err, ldap.LDAPResultInvalidCredentials) {
|
||||
cacheKey := fmt.Sprintf("kubesphere:authfailed:%s:%d", user.Username, time.Now().UnixNano())
|
||||
im.redis.Set(cacheKey, "", im.config.authTimeInterval)
|
||||
if err == ldap.ErrInvalidCredentials {
|
||||
im.cacheClient.Set(authenticationFailedKeyForUsername(username, fmt.Sprintf("%d", time.Now().UnixNano())), "", 30*time.Minute)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
@@ -243,30 +123,25 @@ func (im *imOperator) Login(username, password, ip string) (*oauth2.Token, error
|
||||
}
|
||||
token := jwtutil.MustSigned(claims)
|
||||
|
||||
if !im.config.enableMultiLogin {
|
||||
tokenKey := tokenKeyForUsername(user.Username, "*")
|
||||
if !im.authenticateOptions.MultipleLogin {
|
||||
// multi login not allowed, remove the previous token
|
||||
cacheKey := fmt.Sprintf("kubesphere:users:%s:token:*", user.Username)
|
||||
sessions, err := im.redis.Keys(cacheKey).Result()
|
||||
|
||||
sessions, err := im.cacheClient.Keys(tokenKey)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(sessions) > 0 {
|
||||
klog.V(4).Infoln("revoke token", sessions)
|
||||
err = im.redis.Del(sessions...).Err()
|
||||
err = im.cacheClient.Del(sessions...)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cache token with expiration time
|
||||
cacheKey := fmt.Sprintf("kubesphere:users:%s:token:%s", user.Username, token)
|
||||
if err = im.redis.Set(cacheKey, token, im.config.tokenIdleTimeout).Err(); err != nil {
|
||||
klog.Errorln(err)
|
||||
if err = im.cacheClient.Set(tokenKey, token, im.authenticateOptions.TokenExpiration); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -277,153 +152,39 @@ func (im *imOperator) Login(username, password, ip string) (*oauth2.Token, error
|
||||
|
||||
func (im *imOperator) loginRecord(username, ip string, loginTime time.Time) {
|
||||
if ip != "" {
|
||||
im.redis.RPush(fmt.Sprintf("kubesphere:users:%s:login-log", username), fmt.Sprintf("%s,%s", loginTime.UTC().Format("2006-01-02T15:04:05Z"), ip))
|
||||
im.redis.LTrim(fmt.Sprintf("kubesphere:users:%s:login-log", username), -10, -1)
|
||||
_ = im.cacheClient.Set(loginKeyForUsername(username, loginTime.UTC().Format("2006-01-02T15:04:05Z"), ip), "", 30*24*time.Hour)
|
||||
}
|
||||
}
|
||||
|
||||
func (im *imOperator) LoginHistory(username string) ([]string, error) {
|
||||
data, err := im.redis.LRange(fmt.Sprintf("kubesphere:users:%s:login-log", username), -10, -1).Result()
|
||||
|
||||
keys, err := im.cacheClient.Keys(loginKeyForUsername(username, "*", "*"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
func (im *imOperator) ListUsers(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (im *imOperator) DescribeUser(username string) (*User, error) {
|
||||
conn, err := im.ldap.NewConn()
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
filter := fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", username, username)
|
||||
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
im.ldap.UserSearchBase(),
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
filter,
|
||||
[]string{mailAttribute, descriptionAttribute, preferredLanguageAttribute, createTimestampAttribute},
|
||||
nil,
|
||||
)
|
||||
|
||||
result, err := conn.Search(searchRequest)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(result.Entries) != 1 {
|
||||
return nil, UserNotExists
|
||||
}
|
||||
|
||||
entry := result.Entries[0]
|
||||
|
||||
return convertLdapEntryToUser(entry), nil
|
||||
}
|
||||
|
||||
func convertLdapEntryToUser(entry *ldap.Entry) *User {
|
||||
username := entry.GetAttributeValue(uidAttribute)
|
||||
email := entry.GetAttributeValue(mailAttribute)
|
||||
description := entry.GetAttributeValue(descriptionAttribute)
|
||||
lang := entry.GetAttributeValue(preferredLanguageAttribute)
|
||||
createTimestamp, err := time.Parse(dateTimeLayout, entry.GetAttributeValue(createTimestampAttribute))
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
}
|
||||
return &User{Username: username, Email: email, Description: description, Lang: lang, CreateTime: createTimestamp}
|
||||
func (im *imOperator) DescribeUser(username string) (*iam.User, error) {
|
||||
return im.ldapClient.Get(username)
|
||||
}
|
||||
|
||||
func (im *imOperator) getLastLoginTime(username string) string {
|
||||
cacheKey := fmt.Sprintf("kubesphere:users:%s:login-log", username)
|
||||
lastLogin, err := im.redis.LRange(cacheKey, -1, -1).Result()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if len(lastLogin) > 0 {
|
||||
return strings.Split(lastLogin[0], ",")[0]
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (im *imOperator) DeleteUser(username string) error {
|
||||
conn, err := im.ldap.NewConn()
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
deleteRequest := ldap.NewDelRequest(fmt.Sprintf("uid=%s,%s", username, im.ldap.UserSearchBase()), nil)
|
||||
|
||||
if err = conn.Del(deleteRequest); err != nil {
|
||||
klog.Errorln(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return im.ldapClient.Delete(username)
|
||||
}
|
||||
|
||||
func (im *imOperator) CreateUser(user *User) (*User, error) {
|
||||
user.Username = strings.TrimSpace(user.Username)
|
||||
user.Email = strings.TrimSpace(user.Email)
|
||||
user.Password = strings.TrimSpace(user.Password)
|
||||
user.Description = strings.TrimSpace(user.Description)
|
||||
|
||||
existed, err := im.DescribeUser(user.Username)
|
||||
|
||||
func (im *imOperator) CreateUser(user *iam.User) (*iam.User, error) {
|
||||
err := im.ldapClient.Create(user)
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if existed != nil {
|
||||
return nil, UserAlreadyExists
|
||||
}
|
||||
|
||||
uidNumber := im.uidNumberNext()
|
||||
|
||||
createRequest := ldap.NewAddRequest(fmt.Sprintf("uid=%s,%s", user.Username, im.ldap.UserSearchBase()), nil)
|
||||
createRequest.Attribute("objectClass", []string{"inetOrgPerson", "posixAccount", "top"})
|
||||
createRequest.Attribute("cn", []string{user.Username}) // RFC4519: common name(s) for which the entity is known by
|
||||
createRequest.Attribute("sn", []string{" "}) // RFC2256: last (family) name(s) for which the entity is known by
|
||||
createRequest.Attribute("gidNumber", []string{"500"}) // RFC2307: An integer uniquely identifying a group in an administrative domain
|
||||
createRequest.Attribute("homeDirectory", []string{"/home/" + user.Username}) // The absolute path to the home directory
|
||||
createRequest.Attribute("uid", []string{user.Username}) // RFC4519: user identifier
|
||||
createRequest.Attribute("uidNumber", []string{strconv.Itoa(uidNumber)}) // RFC2307: An integer uniquely identifying a user in an administrative domain
|
||||
createRequest.Attribute("mail", []string{user.Email}) // RFC1274: RFC822 Mailbox
|
||||
createRequest.Attribute("userPassword", []string{user.Password}) // RFC4519/2307: password of user
|
||||
if user.Lang != "" {
|
||||
createRequest.Attribute("preferredLanguage", []string{user.Lang})
|
||||
}
|
||||
if user.Description != "" {
|
||||
createRequest.Attribute("description", []string{user.Description}) // RFC4519: descriptive information
|
||||
}
|
||||
|
||||
conn, err := im.ldap.NewConn()
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = conn.Add(createRequest)
|
||||
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -17,39 +17,3 @@
|
||||
*/
|
||||
|
||||
package iam
|
||||
|
||||
import (
|
||||
"github.com/golang/mock/gomock"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIMOperator(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
ldappool, err := ldap.NewMockClient(&ldap.Options{
|
||||
Host: "192.168.0.7:30389",
|
||||
ManagerDN: "cn=admin,dc=kubesphere,dc=io",
|
||||
ManagerPassword: "admin",
|
||||
UserSearchBase: "ou=Users,dc=kubesphere,dc=io",
|
||||
GroupSearchBase: "ou=Groups,dc=kubesphere,dc=io",
|
||||
InitialCap: 8,
|
||||
MaxCap: 64,
|
||||
}, ctrl, func(client *ldap.MockClient) {
|
||||
client.EXPECT().Search(gomock.Any()).AnyTimes()
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
defer ldappool.Close()
|
||||
|
||||
im := NewIMOperator(ldappool, Config{})
|
||||
|
||||
err = im.Init()
|
||||
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
|
||||
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 iam
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func convertDNToPath(dn string) string {
|
||||
|
||||
paths := regexp.MustCompile("cn=[a-z0-9]([-a-z0-9]*[a-z0-9])?").FindAllString(dn, -1)
|
||||
|
||||
if len(paths) > 1 {
|
||||
for i := 0; i < len(paths); i++ {
|
||||
paths[i] = strings.Replace(paths[i], "cn=", "", 1)
|
||||
}
|
||||
for i, j := 0, len(paths)-1; i < j; i, j = i+1, j-1 {
|
||||
paths[i], paths[j] = paths[j], paths[i]
|
||||
}
|
||||
return strings.Join(paths, ":")
|
||||
} else if len(paths) == 1 {
|
||||
return strings.Replace(paths[0], "cn=", "", -1)
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func splitPath(path string) (searchBase string, cn string) {
|
||||
ldapClient, err := client.ClientSets().Ldap()
|
||||
if err != nil {
|
||||
return "", ""
|
||||
}
|
||||
|
||||
paths := strings.Split(path, ":")
|
||||
length := len(paths)
|
||||
if length > 2 {
|
||||
|
||||
cn = paths[length-1]
|
||||
basePath := paths[:length-1]
|
||||
|
||||
for i := 0; i < len(basePath); i++ {
|
||||
basePath[i] = fmt.Sprintf("cn=%s", basePath[i])
|
||||
}
|
||||
|
||||
for i, j := 0, length-2; i < j; i, j = i+1, j-1 {
|
||||
basePath[i], basePath[j] = basePath[j], basePath[i]
|
||||
}
|
||||
|
||||
searchBase = fmt.Sprintf("%s,%s", strings.Join(basePath, ","), ldapClient.GroupSearchBase())
|
||||
} else if length == 2 {
|
||||
searchBase = fmt.Sprintf("cn=%s,%s", paths[0], ldapClient.GroupSearchBase())
|
||||
cn = paths[1]
|
||||
} else {
|
||||
searchBase = ldapClient.GroupSearchBase()
|
||||
if paths[0] == "" {
|
||||
cn = "*"
|
||||
} else {
|
||||
cn = paths[0]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
*
|
||||
* 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 (
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
KindTokenReview = "TokenReview"
|
||||
)
|
||||
|
||||
type User struct {
|
||||
Username string `json:"username"`
|
||||
Email string `json:"email"`
|
||||
Lang string `json:"lang,omitempty"`
|
||||
Description string `json:"description"`
|
||||
CreateTime time.Time `json:"create_time"`
|
||||
Groups []string `json:"groups,omitempty"`
|
||||
Password string `json:"password,omitempty"`
|
||||
}
|
||||
@@ -20,6 +20,7 @@ package iam
|
||||
|
||||
import (
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
"kubesphere.io/kubesphere/pkg/models/iam/policy"
|
||||
"strings"
|
||||
)
|
||||
@@ -194,15 +195,15 @@ func ContainsUser(subjects interface{}, username string) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
case []User:
|
||||
for _, u := range subjects.([]User) {
|
||||
case []iam.User:
|
||||
for _, u := range subjects.([]iam.User) {
|
||||
if u.Username == username {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
case []*User:
|
||||
for _, u := range subjects.([]*User) {
|
||||
case []*iam.User:
|
||||
for _, u := range subjects.([]*iam.User) {
|
||||
if u.Username == username {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -77,9 +77,9 @@ func NewResourceGetter(factory informers.InformerFactory) *ResourceGetter {
|
||||
resourceGetters[v1alpha2.StorageClasses] = storageclass.NewStorageClassesSearcher(factory.KubernetesSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.HorizontalPodAutoscalers] = hpa.NewHpaSearcher(factory.KubernetesSharedInformerFactory())
|
||||
|
||||
resourceGetters[v1alpha2.S2iBuilders] = s2ibuilder.NewS2iBuilderSearcher(factory.S2iSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.S2iSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.S2iSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.S2iBuilders] = s2ibuilder.NewS2iBuilderSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.S2iRuns] = s2irun.NewS2iRunSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
resourceGetters[v1alpha2.S2iBuilderTemplates] = s2buildertemplate.NewS2iBuidlerTemplateSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
|
||||
resourceGetters[v1alpha2.Workspaces] = workspace.NewWorkspaceSearcher(factory.KubeSphereSharedInformerFactory())
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
package s2buildertemplate
|
||||
|
||||
import (
|
||||
"github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
"github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
|
||||
|
||||
@@ -19,9 +19,9 @@
|
||||
package s2ibuilder
|
||||
|
||||
import (
|
||||
"github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
"github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
|
||||
|
||||
@@ -19,19 +19,15 @@
|
||||
package s2irun
|
||||
|
||||
import (
|
||||
"github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
|
||||
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
"github.com/kubesphere/s2ioperator/pkg/apis/devops/v1alpha1"
|
||||
)
|
||||
|
||||
type s2iRunSearcher struct {
|
||||
|
||||
@@ -108,7 +108,7 @@ func TestListDeployments(t *testing.T) {
|
||||
},
|
||||
api.ListResult{
|
||||
Items: []interface{}{
|
||||
v1.Deployment{
|
||||
&v1.Deployment{
|
||||
ObjectMeta: metaV1.ObjectMeta{
|
||||
Name: "foo-2",
|
||||
Namespace: "bar",
|
||||
@@ -141,7 +141,7 @@ func TestListDeployments(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(got, test.expected); diff != "" {
|
||||
if diff := cmp.Diff(got.Items, test.expected.Items); diff != "" {
|
||||
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -77,7 +77,7 @@ func (t *tenantOperator) DeleteNamespace(workspace, namespace string) error {
|
||||
}
|
||||
|
||||
func New(client kubernetes.Interface, informers k8sinformers.SharedInformerFactory, ksinformers ksinformers.SharedInformerFactory, db *mysql.Database) Interface {
|
||||
amOperator := iam.NewAMOperator(informers)
|
||||
amOperator := iam.NewAMOperator(client, informers)
|
||||
return &tenantOperator{
|
||||
workspaces: newWorkspaceOperator(client, informers, ksinformers, amOperator, db),
|
||||
namespaces: newNamespaceOperator(client, informers, amOperator),
|
||||
|
||||
@@ -33,7 +33,6 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/models/iam"
|
||||
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
|
||||
"kubesphere.io/kubesphere/pkg/server/params"
|
||||
clientset "kubesphere.io/kubesphere/pkg/simple/client"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||
"sort"
|
||||
@@ -43,10 +42,12 @@ import (
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
|
||||
iamapi "kubesphere.io/kubesphere/pkg/api/iam"
|
||||
)
|
||||
|
||||
type InWorkspaceUser struct {
|
||||
*iam.User
|
||||
*iamapi.User
|
||||
WorkspaceRole string `json:"workspaceRole"`
|
||||
}
|
||||
|
||||
@@ -203,10 +204,6 @@ func (w *workspaceOperator) deleteWorkspaceRoleBinding(workspace, username strin
|
||||
}
|
||||
|
||||
func (w *workspaceOperator) CountDevopsProjectsInWorkspace(workspaceName string) (int, error) {
|
||||
if w.db == nil {
|
||||
return 0, clientset.ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
query := w.db.Select(devops.DevOpsProjectIdColumn).
|
||||
From(devops.DevOpsProjectTableName).
|
||||
Where(db.And(db.Eq(devops.DevOpsProjectWorkSpaceColumn, workspaceName),
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/spf13/pflag"
|
||||
"kubesphere.io/kubesphere/pkg/utils/net"
|
||||
"os"
|
||||
)
|
||||
|
||||
type ServerRunOptions struct {
|
||||
@@ -63,10 +64,18 @@ func (s *ServerRunOptions) Validate() []error {
|
||||
if net.IsValidPort(s.SecurePort) {
|
||||
if s.TlsCertFile == "" {
|
||||
errs = append(errs, fmt.Errorf("tls cert file is empty while secure serving"))
|
||||
} else {
|
||||
if _, err := os.Stat(s.TlsCertFile); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
|
||||
if s.TlsPrivateKey == "" {
|
||||
errs = append(errs, fmt.Errorf("tls private key file is empty while secure serving"))
|
||||
} else {
|
||||
if _, err := os.Stat(s.TlsPrivateKey); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
pkg/simple/client/cache/cache.go
vendored
4
pkg/simple/client/cache/cache.go
vendored
@@ -13,10 +13,10 @@ type Interface interface {
|
||||
Set(key string, value string, duration time.Duration) error
|
||||
|
||||
// Del deletes the given key, no error returned if the key doesn't exists
|
||||
Del(key string) error
|
||||
Del(keys ...string) error
|
||||
|
||||
// Exists checks the existence of a give key
|
||||
Exists(key string) (bool, error)
|
||||
Exists(keys ...string) (bool, error)
|
||||
|
||||
// Expires updates object's expiration time, return err if key doesn't exist
|
||||
Expire(key string, duration time.Duration) error
|
||||
|
||||
21
pkg/simple/client/cache/redis.go
vendored
21
pkg/simple/client/cache/redis.go
vendored
@@ -63,25 +63,30 @@ func NewRedisClient(option *Options, stopCh <-chan struct{}) (Interface, error)
|
||||
}
|
||||
|
||||
func (r *Client) Get(key string) (string, error) {
|
||||
return "", nil
|
||||
return r.client.Get(key).Result()
|
||||
}
|
||||
|
||||
func (r *Client) Keys(pattern string) ([]string, error) {
|
||||
panic("implement me")
|
||||
return r.client.Keys(pattern).Result()
|
||||
}
|
||||
|
||||
func (r *Client) Set(key string, value string, duration time.Duration) error {
|
||||
panic("implement me")
|
||||
return r.client.Set(key, value, duration).Err()
|
||||
}
|
||||
|
||||
func (r *Client) Del(key string) error {
|
||||
panic("implement me")
|
||||
func (r *Client) Del(keys ...string) error {
|
||||
return r.client.Del(keys...).Err()
|
||||
}
|
||||
|
||||
func (r *Client) Exists(key string) (bool, error) {
|
||||
panic("implement me")
|
||||
func (r *Client) Exists(keys ...string) (bool, error) {
|
||||
existedKeys, err := r.client.Exists(keys...).Result()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return len(keys) == int(existedKeys), nil
|
||||
}
|
||||
|
||||
func (r *Client) Expire(key string, duration time.Duration) error {
|
||||
panic("implement me")
|
||||
return r.client.Expire(key, duration).Err()
|
||||
}
|
||||
|
||||
4
pkg/simple/client/cache/simple_cache.go
vendored
4
pkg/simple/client/cache/simple_cache.go
vendored
@@ -23,7 +23,7 @@ func (s *SimpleCache) Set(key string, value string, duration time.Duration) erro
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Del(key string) error {
|
||||
func (s *SimpleCache) Del(keys ...string) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ func (s *SimpleCache) Get(key string) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *SimpleCache) Exists(key string) (bool, error) {
|
||||
func (s *SimpleCache) Exists(keys ...string) (bool, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
|
||||
@@ -14,21 +14,11 @@ limitations under the License.
|
||||
package jenkins
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"k8s.io/klog"
|
||||
"sync"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
)
|
||||
|
||||
const (
|
||||
jenkinsAllUserRoleName = "kubesphere-user"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
jenkinsClient *Jenkins
|
||||
}
|
||||
|
||||
func NewDevopsClient(options *Options) (*Client, error) {
|
||||
var d Client
|
||||
func NewDevopsClient(options *Options) (devops.Interface, error) {
|
||||
|
||||
jenkins := CreateJenkins(nil, options.Host, options.MaxConnections, options.Username, options.Password)
|
||||
jenkins, err := jenkins.Init()
|
||||
@@ -37,51 +27,5 @@ func NewDevopsClient(options *Options) (*Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
d.jenkinsClient = jenkins
|
||||
|
||||
err = d.initializeJenkins()
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d, nil
|
||||
}
|
||||
|
||||
func (c *Client) Jenkins() *Jenkins {
|
||||
return c.jenkinsClient
|
||||
}
|
||||
|
||||
var mutex = sync.Mutex{}
|
||||
|
||||
func (c *Client) initializeJenkins() error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if c.jenkinsClient == nil {
|
||||
return fmt.Errorf("jenkins intialization failed")
|
||||
}
|
||||
|
||||
globalRole, err := c.jenkinsClient.GetGlobalRole(jenkinsAllUserRoleName)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Jenkins uninitialized, create global role
|
||||
if globalRole == nil {
|
||||
_, err := c.jenkinsClient.AddGlobalRole(jenkinsAllUserRoleName, GlobalPermissionIds{GlobalRead: true}, true)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
_, err = c.jenkinsClient.AddProjectRole(jenkinsAllUserRoleName, "\\n\\s*\\r", ProjectPermissionIds{SCMTag: true}, true)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return jenkins, nil
|
||||
}
|
||||
|
||||
@@ -1,368 +0,0 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/cache"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"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/ldap"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/logging/elasticsearch"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/monitoring"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/monitoring/prometheus"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/s3"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var ErrClientSetNotEnabled = errors.New("client set not enabled")
|
||||
|
||||
type ClientSetOptions struct {
|
||||
mySQLOptions *mysql.Options
|
||||
redisOptions *cache.Options
|
||||
kubernetesOptions *k8s.KubernetesOptions
|
||||
devopsOptions *jenkins.Options
|
||||
sonarqubeOptions *sonarqube.Options
|
||||
ldapOptions *ldap.Options
|
||||
s3Options *s3.Options
|
||||
openPitrixOptions *openpitrix.Options
|
||||
prometheusOptions *prometheus.Options
|
||||
kubesphereOptions *kubesphere.Options
|
||||
elasticsearhOptions *elasticsearch.Options
|
||||
}
|
||||
|
||||
func NewClientSetOptions() *ClientSetOptions {
|
||||
return &ClientSetOptions{
|
||||
mySQLOptions: mysql.NewMySQLOptions(),
|
||||
redisOptions: cache.NewRedisOptions(),
|
||||
kubernetesOptions: k8s.NewKubernetesOptions(),
|
||||
ldapOptions: ldap.NewOptions(),
|
||||
devopsOptions: jenkins.NewDevopsOptions(),
|
||||
sonarqubeOptions: sonarqube.NewSonarQubeOptions(),
|
||||
s3Options: s3.NewS3Options(),
|
||||
openPitrixOptions: openpitrix.NewOptions(),
|
||||
prometheusOptions: prometheus.NewPrometheusOptions(),
|
||||
kubesphereOptions: kubesphere.NewKubeSphereOptions(),
|
||||
elasticsearhOptions: elasticsearch.NewElasticSearchOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetMySQLOptions(options *mysql.Options) *ClientSetOptions {
|
||||
c.mySQLOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetRedisOptions(options *cache.Options) *ClientSetOptions {
|
||||
c.redisOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetKubernetesOptions(options *k8s.KubernetesOptions) *ClientSetOptions {
|
||||
c.kubernetesOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetDevopsOptions(options *jenkins.Options) *ClientSetOptions {
|
||||
c.devopsOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetLdapOptions(options *ldap.Options) *ClientSetOptions {
|
||||
c.ldapOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetS3Options(options *s3.Options) *ClientSetOptions {
|
||||
c.s3Options = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetOpenPitrixOptions(options *openpitrix.Options) *ClientSetOptions {
|
||||
c.openPitrixOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetPrometheusOptions(options *prometheus.Options) *ClientSetOptions {
|
||||
c.prometheusOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetSonarQubeOptions(options *sonarqube.Options) *ClientSetOptions {
|
||||
c.sonarqubeOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetKubeSphereOptions(options *kubesphere.Options) *ClientSetOptions {
|
||||
c.kubesphereOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *ClientSetOptions) SetElasticSearchOptions(options *elasticsearch.Options) *ClientSetOptions {
|
||||
c.elasticsearhOptions = options
|
||||
return c
|
||||
}
|
||||
|
||||
// ClientSet provide best of effort service to initialize clients,
|
||||
// but there is no guarantee to return a valid client instance,
|
||||
// so do validity check before use
|
||||
type ClientSet struct {
|
||||
csoptions *ClientSetOptions
|
||||
stopCh <-chan struct{}
|
||||
|
||||
mySQLClient *mysql.Client
|
||||
|
||||
k8sClient k8s.Client
|
||||
ldapClient ldap.Client
|
||||
devopsClient *jenkins.Client
|
||||
sonarQubeClient *sonarqube.Client
|
||||
redisClient cache.Interface
|
||||
s3Client s3.Interface
|
||||
prometheusClient monitoring.Interface
|
||||
openpitrixClient openpitrix.Client
|
||||
kubesphereClient *kubesphere.Client
|
||||
elasticSearchClient *elasticsearch.Elasticsearch
|
||||
}
|
||||
|
||||
var mutex sync.Mutex
|
||||
|
||||
// global clientsets instance
|
||||
var sharedClientSet *ClientSet
|
||||
|
||||
func ClientSets() *ClientSet {
|
||||
return sharedClientSet
|
||||
}
|
||||
|
||||
func NewClientSetFactory(c *ClientSetOptions, stopCh <-chan struct{}) *ClientSet {
|
||||
sharedClientSet = &ClientSet{csoptions: c, stopCh: stopCh}
|
||||
|
||||
if c.kubernetesOptions != nil {
|
||||
sharedClientSet.k8sClient = k8s.NewKubernetesClientOrDie(c.kubernetesOptions)
|
||||
}
|
||||
|
||||
if c.kubesphereOptions != nil {
|
||||
sharedClientSet.kubesphereClient = kubesphere.NewKubeSphereClient(c.kubesphereOptions)
|
||||
}
|
||||
|
||||
return sharedClientSet
|
||||
}
|
||||
|
||||
// lazy creating
|
||||
func (cs *ClientSet) MySQL() (*mysql.Database, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.mySQLOptions == nil || cs.csoptions.mySQLOptions.Host == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.mySQLClient != nil {
|
||||
return cs.mySQLClient.Database(), nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
if cs.mySQLClient == nil {
|
||||
cs.mySQLClient, err = mysql.NewMySQLClient(cs.csoptions.mySQLOptions, cs.stopCh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return cs.mySQLClient.Database(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClientSet) Cache() (cache.Interface, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.redisOptions == nil || cs.csoptions.redisOptions.RedisURL == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.redisClient != nil {
|
||||
return cs.redisClient, nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
if cs.redisClient == nil {
|
||||
cs.redisClient, err = cache.NewRedisClient(cs.csoptions.redisOptions, cs.stopCh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return cs.redisClient, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClientSet) Devops() (devops.Interface, error) {
|
||||
//var err error
|
||||
//
|
||||
//if cs.csoptions.devopsOptions == nil || cs.csoptions.devopsOptions.Host == "" {
|
||||
// return nil, ErrClientSetNotEnabled
|
||||
//}
|
||||
//
|
||||
//if cs.devopsClient != nil {
|
||||
// return cs.devopsClient, nil
|
||||
//} else {
|
||||
// mutex.Lock()
|
||||
// defer mutex.Unlock()
|
||||
//
|
||||
// if cs.devopsClient == nil {
|
||||
// cs.devopsClient, err = jenkins.NewDevopsClient(cs.csoptions.devopsOptions)
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
// }
|
||||
// return cs.devopsClient, nil
|
||||
//}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (cs *ClientSet) SonarQube() (*sonarqube.Client, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.sonarqubeOptions == nil || cs.csoptions.sonarqubeOptions.Host == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.sonarQubeClient != nil {
|
||||
return cs.sonarQubeClient, nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if cs.sonarQubeClient == nil {
|
||||
cs.sonarQubeClient, err = sonarqube.NewSonarQubeClient(cs.csoptions.sonarqubeOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cs.sonarQubeClient, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClientSet) Ldap() (ldap.Client, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.ldapOptions == nil || cs.csoptions.ldapOptions.Host == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.ldapClient != nil {
|
||||
return cs.ldapClient, nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if cs.ldapClient == nil {
|
||||
cs.ldapClient, err = ldap.NewClient(cs.csoptions.ldapOptions, cs.stopCh)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cs.ldapClient, nil
|
||||
}
|
||||
}
|
||||
|
||||
// since kubernetes client is required, we will
|
||||
// create it on setup
|
||||
func (cs *ClientSet) K8s() k8s.Client {
|
||||
return cs.k8sClient
|
||||
}
|
||||
|
||||
func (cs *ClientSet) S3() (s3.Interface, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.s3Options == nil || cs.csoptions.s3Options.Endpoint == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.s3Client != nil {
|
||||
return cs.s3Client, nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if cs.s3Client == nil {
|
||||
cs.s3Client, err = s3.NewS3Client(cs.csoptions.s3Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return cs.s3Client, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClientSet) OpenPitrix() (openpitrix.Client, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.openPitrixOptions == nil ||
|
||||
cs.csoptions.openPitrixOptions.RepoManagerEndpoint == "" ||
|
||||
cs.csoptions.openPitrixOptions.RuntimeManagerEndpoint == "" ||
|
||||
cs.csoptions.openPitrixOptions.ClusterManagerEndpoint == "" ||
|
||||
cs.csoptions.openPitrixOptions.AppManagerEndpoint == "" ||
|
||||
cs.csoptions.openPitrixOptions.AttachmentManagerEndpoint == "" ||
|
||||
cs.csoptions.openPitrixOptions.RepoIndexerEndpoint == "" ||
|
||||
cs.csoptions.openPitrixOptions.CategoryManagerEndpoint == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.openpitrixClient != nil {
|
||||
return cs.openpitrixClient, nil
|
||||
} else {
|
||||
cs.openpitrixClient, err = openpitrix.NewClient(cs.csoptions.openPitrixOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cs.openpitrixClient, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClientSet) MonitoringClient() (monitoring.Interface, error) {
|
||||
if cs.csoptions.prometheusOptions == nil || cs.csoptions.prometheusOptions.Endpoint == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.prometheusClient != nil {
|
||||
return cs.prometheusClient, nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if cs.prometheusClient == nil {
|
||||
cs.prometheusClient = prometheus.NewPrometheus(cs.csoptions.prometheusOptions)
|
||||
}
|
||||
return cs.prometheusClient, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (cs *ClientSet) KubeSphere() *kubesphere.Client {
|
||||
return cs.kubesphereClient
|
||||
}
|
||||
|
||||
func (cs *ClientSet) ElasticSearch() (*elasticsearch.Elasticsearch, error) {
|
||||
var err error
|
||||
|
||||
if cs.csoptions.elasticsearhOptions == nil || cs.csoptions.elasticsearhOptions.Host == "" {
|
||||
return nil, ErrClientSetNotEnabled
|
||||
}
|
||||
|
||||
if cs.elasticSearchClient != nil {
|
||||
return cs.elasticSearchClient, nil
|
||||
} else {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
if cs.elasticSearchClient == nil {
|
||||
cs.elasticSearchClient, err = elasticsearch.NewElasticsearch(cs.csoptions.elasticsearhOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return cs.elasticSearchClient, nil
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ package k8s
|
||||
|
||||
import (
|
||||
applicationclientset "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned"
|
||||
s2i "github.com/kubesphere/s2ioperator/pkg/client/clientset/versioned"
|
||||
istioclient "istio.io/client-go/pkg/clientset/versioned"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
type Client interface {
|
||||
Kubernetes() kubernetes.Interface
|
||||
KubeSphere() kubesphere.Interface
|
||||
S2i() s2i.Interface
|
||||
Istio() istioclient.Interface
|
||||
Application() applicationclientset.Interface
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
Master() string
|
||||
@@ -23,17 +23,17 @@ type Client interface {
|
||||
|
||||
type kubernetesClient struct {
|
||||
// kubernetes client interface
|
||||
k8s *kubernetes.Clientset
|
||||
k8s kubernetes.Interface
|
||||
|
||||
// discovery client
|
||||
discoveryClient *discovery.DiscoveryClient
|
||||
|
||||
// generated clientset
|
||||
ks *kubesphere.Clientset
|
||||
ks kubesphere.Interface
|
||||
|
||||
s2i *s2i.Clientset
|
||||
application applicationclientset.Interface
|
||||
|
||||
application *applicationclientset.Clientset
|
||||
istio istioclient.Interface
|
||||
|
||||
master string
|
||||
|
||||
@@ -54,7 +54,7 @@ func NewKubernetesClientOrDie(options *KubernetesOptions) Client {
|
||||
k8s: kubernetes.NewForConfigOrDie(config),
|
||||
discoveryClient: discovery.NewDiscoveryClientForConfigOrDie(config),
|
||||
ks: kubesphere.NewForConfigOrDie(config),
|
||||
s2i: s2i.NewForConfigOrDie(config),
|
||||
istio: istioclient.NewForConfigOrDie(config),
|
||||
application: applicationclientset.NewForConfigOrDie(config),
|
||||
master: config.Host,
|
||||
config: config,
|
||||
@@ -93,11 +93,6 @@ func NewKubernetesClient(options *KubernetesOptions) (Client, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k.s2i, err = s2i.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
k.application, err = applicationclientset.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -121,14 +116,14 @@ func (k *kubernetesClient) KubeSphere() kubesphere.Interface {
|
||||
return k.ks
|
||||
}
|
||||
|
||||
func (k *kubernetesClient) S2i() s2i.Interface {
|
||||
return k.s2i
|
||||
}
|
||||
|
||||
func (k *kubernetesClient) Application() applicationclientset.Interface {
|
||||
return k.application
|
||||
}
|
||||
|
||||
func (k *kubernetesClient) Istio() istioclient.Interface {
|
||||
return k.istio
|
||||
}
|
||||
|
||||
// master address used to generate kubeconfig for downloading
|
||||
func (k *kubernetesClient) Master() string {
|
||||
return k.master
|
||||
|
||||
@@ -20,103 +20,360 @@ package ldap
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/go-ldap/ldap"
|
||||
"github.com/golang/mock/gomock"
|
||||
"k8s.io/klog"
|
||||
"github.com/google/uuid"
|
||||
"kubesphere.io/kubesphere/pkg/api/iam"
|
||||
"kubesphere.io/kubesphere/pkg/server/errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
NewConn() (ldap.Client, error)
|
||||
Close()
|
||||
GroupSearchBase() string
|
||||
UserSearchBase() string
|
||||
type Interface interface {
|
||||
// Create create a new user in ldap
|
||||
Create(user *iam.User) error
|
||||
|
||||
// Update updates a user information, return error if user not exists
|
||||
Update(user *iam.User) error
|
||||
|
||||
// Delete deletes a user from ldap, return nil if user not exists
|
||||
Delete(name string) error
|
||||
|
||||
// Get gets a user by its username from ldap
|
||||
Get(name string) (*iam.User, error)
|
||||
|
||||
//
|
||||
Verify(name string, password string) error
|
||||
}
|
||||
|
||||
type poolClient struct {
|
||||
pool Pool
|
||||
options *Options
|
||||
const (
|
||||
ldapAttributeObjectClass = "objectClass"
|
||||
ldapAttributeCommonName = "cn"
|
||||
ldapAttributeSerialNumber = "sn"
|
||||
ldapAttributeGlobalIDNumber = "gidNumber"
|
||||
ldapAttributeHomeDirectory = "homeDirectory"
|
||||
ldapAttributeUserID = "uid"
|
||||
ldapAttributeUserIDNumber = "uidNumber"
|
||||
ldapAttributeMail = "mail"
|
||||
ldapAttributeUserPassword = "userPassword"
|
||||
ldapAttributePreferredLanguage = "preferredLanguage"
|
||||
ldapAttributeDescription = "description"
|
||||
ldapAttributeCreateTimestamp = "createTimestamp"
|
||||
ldapAttributeOrganizationUnit = "ou"
|
||||
|
||||
// ldap create timestamp attribute layout
|
||||
ldapAttributeCreateTimestampLayout = "20060102150405Z"
|
||||
)
|
||||
|
||||
var ErrUserAlreadyExisted = errors.New("user already existed")
|
||||
var ErrUserNotExists = errors.New("user not exists")
|
||||
var ErrInvalidCredentials = errors.New("invalid credentials")
|
||||
|
||||
type ldapInterfaceImpl struct {
|
||||
pool Pool
|
||||
userSearchBase string
|
||||
groupSearchBase string
|
||||
managerDN string
|
||||
managerPassword string
|
||||
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// panic if cannot connect to ldap service
|
||||
func NewClient(options *Options, stopCh <-chan struct{}) (Client, error) {
|
||||
pool, err := newChannelPool(options.InitialCap, options.MaxCap, options.PoolName, func(s string) (ldap.Client, error) {
|
||||
var _ Interface = &ldapInterfaceImpl{}
|
||||
|
||||
func NewLdapClient(options *Options, stopCh <-chan struct{}) (Interface, error) {
|
||||
|
||||
poolFactory := func(s string) (ldap.Client, error) {
|
||||
conn, err := ldap.Dial("tcp", options.Host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}, []uint16{ldap.LDAPResultAdminLimitExceeded, ldap.ErrorNetwork})
|
||||
}
|
||||
|
||||
pool, err := newChannelPool(options.InitialCap,
|
||||
options.MaxCap,
|
||||
options.PoolName,
|
||||
poolFactory,
|
||||
[]uint16{ldap.LDAPResultAdminLimitExceeded, ldap.ErrorNetwork})
|
||||
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &poolClient{
|
||||
pool: pool,
|
||||
options: options,
|
||||
client := &ldapInterfaceImpl{
|
||||
pool: pool,
|
||||
userSearchBase: options.UserSearchBase,
|
||||
groupSearchBase: options.GroupSearchBase,
|
||||
managerDN: options.ManagerDN,
|
||||
managerPassword: options.ManagerPassword,
|
||||
once: sync.Once{},
|
||||
}
|
||||
|
||||
go func() {
|
||||
<-stopCh
|
||||
client.Close()
|
||||
client.close()
|
||||
}()
|
||||
|
||||
client.once.Do(func() {
|
||||
_ = client.createSearchBase()
|
||||
})
|
||||
|
||||
return client, nil
|
||||
}
|
||||
func (l *poolClient) Close() {
|
||||
|
||||
func (l *ldapInterfaceImpl) createSearchBase() error {
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
createIfNotExistsFunc := func(request *ldap.AddRequest) error {
|
||||
searchRequest := &ldap.SearchRequest{
|
||||
BaseDN: request.DN,
|
||||
Scope: ldap.ScopeWholeSubtree,
|
||||
DerefAliases: ldap.NeverDerefAliases,
|
||||
SizeLimit: 0,
|
||||
TimeLimit: 0,
|
||||
TypesOnly: false,
|
||||
Filter: "(objectClass=*)",
|
||||
}
|
||||
|
||||
_, err = conn.Search(searchRequest)
|
||||
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
|
||||
return conn.Add(request)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
userSearchBaseAddRequest := &ldap.AddRequest{
|
||||
DN: l.userSearchBase,
|
||||
Attributes: []ldap.Attribute{
|
||||
{
|
||||
Type: ldapAttributeObjectClass,
|
||||
Vals: []string{"organizationalUnit", "top"},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeOrganizationUnit,
|
||||
Vals: []string{"Users"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err = createIfNotExistsFunc(userSearchBaseAddRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
groupSearchBaseAddRequest := *userSearchBaseAddRequest
|
||||
groupSearchBaseAddRequest.DN = l.groupSearchBase
|
||||
|
||||
return createIfNotExistsFunc(&groupSearchBaseAddRequest)
|
||||
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) close() {
|
||||
if l.pool != nil {
|
||||
l.pool.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func (l *poolClient) NewConn() (ldap.Client, error) {
|
||||
if l.pool == nil {
|
||||
err := fmt.Errorf("ldap connection pool is not initialized")
|
||||
klog.Errorln(err)
|
||||
func (l *ldapInterfaceImpl) newConn() (ldap.Client, error) {
|
||||
conn, err := l.pool.Get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conn, err := l.pool.Get()
|
||||
// cannot connect to ldap server or pool is closed
|
||||
if err != nil {
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
err = conn.Bind(l.options.ManagerDN, l.options.ManagerPassword)
|
||||
err = conn.Bind(l.managerDN, l.managerPassword)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
klog.Errorln(err)
|
||||
return nil, err
|
||||
}
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (l *poolClient) GroupSearchBase() string {
|
||||
return l.options.GroupSearchBase
|
||||
func (l *ldapInterfaceImpl) dnForUsername(username string) string {
|
||||
return fmt.Sprintf("uid=%s,%s", username, l.userSearchBase)
|
||||
}
|
||||
|
||||
func (l *poolClient) UserSearchBase() string {
|
||||
return l.options.UserSearchBase
|
||||
func (l *ldapInterfaceImpl) filterForUsername(username string) string {
|
||||
return fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", username, username)
|
||||
}
|
||||
|
||||
func NewMockClient(options *Options, ctrl *gomock.Controller, setup func(client *MockClient)) (Client, error) {
|
||||
pool, err := newChannelPool(options.InitialCap, options.MaxCap, options.PoolName, func(s string) (ldap.Client, error) {
|
||||
conn := newMockClient(ctrl)
|
||||
conn.EXPECT().Bind(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
conn.EXPECT().Close().AnyTimes()
|
||||
setup(conn)
|
||||
return conn, nil
|
||||
}, []uint16{ldap.LDAPResultAdminLimitExceeded, ldap.ErrorNetwork})
|
||||
|
||||
func (l *ldapInterfaceImpl) Get(name string) (*iam.User, error) {
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
searchRequest := &ldap.SearchRequest{
|
||||
BaseDN: l.userSearchBase,
|
||||
Scope: ldap.ScopeWholeSubtree,
|
||||
DerefAliases: ldap.NeverDerefAliases,
|
||||
SizeLimit: 0,
|
||||
TimeLimit: 0,
|
||||
TypesOnly: false,
|
||||
Filter: l.filterForUsername(name),
|
||||
Attributes: []string{
|
||||
ldapAttributeMail,
|
||||
ldapAttributeDescription,
|
||||
ldapAttributePreferredLanguage,
|
||||
ldapAttributeCreateTimestamp,
|
||||
},
|
||||
}
|
||||
|
||||
searchResults, err := conn.Search(searchRequest)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client := &poolClient{
|
||||
pool: pool,
|
||||
options: options,
|
||||
if len(searchResults.Entries) != 1 {
|
||||
return nil, ErrUserNotExists
|
||||
}
|
||||
|
||||
return client, nil
|
||||
userEntry := searchResults.Entries[0]
|
||||
|
||||
user := &iam.User{
|
||||
Username: userEntry.GetAttributeValue(ldapAttributeUserID),
|
||||
Email: userEntry.GetAttributeValue(ldapAttributeMail),
|
||||
Lang: userEntry.GetAttributeValue(ldapAttributePreferredLanguage),
|
||||
Description: userEntry.GetAttributeValue(ldapAttributeDescription),
|
||||
}
|
||||
|
||||
createTimestamp, _ := time.Parse(ldapAttributeCreateTimestampLayout, userEntry.GetAttributeValue(ldapAttributeCreateTimestamp))
|
||||
user.CreateTime = createTimestamp
|
||||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) Create(user *iam.User) error {
|
||||
if _, err := l.Get(user.Username); err != nil {
|
||||
return ErrUserAlreadyExisted
|
||||
}
|
||||
|
||||
createRequest := &ldap.AddRequest{
|
||||
DN: l.dnForUsername(user.Username),
|
||||
Attributes: []ldap.Attribute{
|
||||
{
|
||||
Type: ldapAttributeObjectClass,
|
||||
Vals: []string{"inetOrgPerson", "posixAccount", "top"},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeCommonName,
|
||||
Vals: []string{user.Username},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeSerialNumber,
|
||||
Vals: []string{" "},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeGlobalIDNumber,
|
||||
Vals: []string{"500"},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeHomeDirectory,
|
||||
Vals: []string{"/home/" + user.Username},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeUserID,
|
||||
Vals: []string{user.Username},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeUserIDNumber,
|
||||
Vals: []string{uuid.New().String()},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeMail,
|
||||
Vals: []string{user.Email},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeUserPassword,
|
||||
Vals: []string{user.Password},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributePreferredLanguage,
|
||||
Vals: []string{user.Lang},
|
||||
},
|
||||
{
|
||||
Type: ldapAttributeDescription,
|
||||
Vals: []string{user.Description},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
return conn.Add(createRequest)
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) Delete(name string) error {
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
_, err = l.Get(name)
|
||||
if err != nil {
|
||||
if err == ErrUserNotExists {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
deleteRequest := &ldap.DelRequest{
|
||||
DN: l.dnForUsername(name),
|
||||
}
|
||||
|
||||
return conn.Del(deleteRequest)
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) Update(newUser *iam.User) error {
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
// check user existed
|
||||
_, err = l.Get(newUser.Username)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
modifyRequest := &ldap.ModifyRequest{
|
||||
DN: l.dnForUsername(newUser.Username),
|
||||
}
|
||||
|
||||
if newUser.Description != "" {
|
||||
modifyRequest.Replace(ldapAttributeDescription, []string{newUser.Description})
|
||||
}
|
||||
|
||||
if newUser.Lang != "" {
|
||||
modifyRequest.Replace(ldapAttributePreferredLanguage, []string{newUser.Lang})
|
||||
}
|
||||
|
||||
if newUser.Password != "" {
|
||||
modifyRequest.Replace(ldapAttributeUserPassword, []string{newUser.Password})
|
||||
}
|
||||
|
||||
return conn.Modify(modifyRequest)
|
||||
|
||||
}
|
||||
|
||||
func (l *ldapInterfaceImpl) Verify(username, password string) error {
|
||||
conn, err := l.newConn()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dn := l.dnForUsername(username)
|
||||
err = conn.Bind(dn, password)
|
||||
if ldap.IsErrorWithCode(err, ldap.LDAPResultInvalidCredentials) {
|
||||
return ErrInvalidCredentials
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user