devlopment branch (#1736)

This commit is contained in:
zryfish
2020-01-02 20:52:00 +08:00
committed by GitHub
parent ff0ffe8650
commit eceadec69c
440 changed files with 61524 additions and 3699 deletions

View File

@@ -10,16 +10,16 @@ import (
"kubesphere.io/kubesphere/pkg/simple/client/devops" "kubesphere.io/kubesphere/pkg/simple/client/devops"
"kubesphere.io/kubesphere/pkg/simple/client/k8s" "kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/simple/client/s2is3" "kubesphere.io/kubesphere/pkg/simple/client/s3"
"strings" "strings"
"time" "time"
) )
type KubeSphereControllerManagerOptions struct { type KubeSphereControllerManagerOptions struct {
KubernetesOptions *k8s.KubernetesOptions KubernetesOptions *k8s.KubernetesOptions
DevopsOptions *devops.DevopsOptions DevopsOptions *devops.Options
S3Options *s2is3.S3Options S3Options *s3.Options
OpenPitrixOptions *openpitrix.OpenPitrixOptions OpenPitrixOptions *openpitrix.Options
LeaderElection *leaderelection.LeaderElectionConfig LeaderElection *leaderelection.LeaderElectionConfig
} }
@@ -28,7 +28,7 @@ func NewKubeSphereControllerManagerOptions() *KubeSphereControllerManagerOptions
s := &KubeSphereControllerManagerOptions{ s := &KubeSphereControllerManagerOptions{
KubernetesOptions: k8s.NewKubernetesOptions(), KubernetesOptions: k8s.NewKubernetesOptions(),
DevopsOptions: devops.NewDevopsOptions(), DevopsOptions: devops.NewDevopsOptions(),
S3Options: s2is3.NewS3Options(), S3Options: s3.NewS3Options(),
OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(), OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(),
LeaderElection: &leaderelection.LeaderElectionConfig{ LeaderElection: &leaderelection.LeaderElectionConfig{
LeaseDuration: 30 * time.Second, LeaseDuration: 30 * time.Second,
@@ -47,13 +47,13 @@ func (s *KubeSphereControllerManagerOptions) ApplyTo(conf *kubesphereconfig.Conf
s.OpenPitrixOptions.ApplyTo(conf.OpenPitrixOptions) s.OpenPitrixOptions.ApplyTo(conf.OpenPitrixOptions)
} }
func (s *KubeSphereControllerManagerOptions) Flags() cliflag.NamedFlagSets { func (s *KubeSphereControllerManagerOptions) Flags(o *KubeSphereControllerManagerOptions) cliflag.NamedFlagSets {
fss := cliflag.NamedFlagSets{} fss := cliflag.NamedFlagSets{}
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes")) s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), o.KubernetesOptions)
s.DevopsOptions.AddFlags(fss.FlagSet("devops")) s.DevopsOptions.AddFlags(fss.FlagSet("devops"), o.DevopsOptions)
s.S3Options.AddFlags(fss.FlagSet("s3")) s.S3Options.AddFlags(fss.FlagSet("s3"), o.S3Options)
s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix")) s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), o.OpenPitrixOptions)
fs := fss.FlagSet("leaderelection") fs := fss.FlagSet("leaderelection")
s.bindLeaderElectionFlags(s.LeaderElection, fs) s.bindLeaderElectionFlags(s.LeaderElection, fs)

View File

@@ -69,8 +69,10 @@ func NewControllerManagerCommand() *cobra.Command {
}, },
} }
conf := loadConfFromFile()
fs := cmd.Flags() fs := cmd.Flags()
namedFlagSets := s.Flags() namedFlagSets := s.Flags(conf)
for _, f := range namedFlagSets.FlagSets { for _, f := range namedFlagSets.FlagSets {
fs.AddFlagSet(f) fs.AddFlagSet(f)
@@ -119,6 +121,22 @@ func CreateClientSet(conf *controllerconfig.Config, stopCh <-chan struct{}) erro
return nil 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 { func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{}) error {
err := CreateClientSet(controllerconfig.Get(), stopCh) err := CreateClientSet(controllerconfig.Get(), stopCh)
if err != nil { if err != nil {

View File

@@ -11,24 +11,24 @@ import (
"kubesphere.io/kubesphere/pkg/simple/client/mysql" "kubesphere.io/kubesphere/pkg/simple/client/mysql"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/simple/client/prometheus" "kubesphere.io/kubesphere/pkg/simple/client/prometheus"
"kubesphere.io/kubesphere/pkg/simple/client/s2is3" "kubesphere.io/kubesphere/pkg/simple/client/s3"
"kubesphere.io/kubesphere/pkg/simple/client/servicemesh" "kubesphere.io/kubesphere/pkg/simple/client/servicemesh"
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube" "kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
"strings" "strings"
) )
type ServerRunOptions struct { type ServerRunOptions struct {
ConfigFile string
GenericServerRunOptions *genericoptions.ServerRunOptions GenericServerRunOptions *genericoptions.ServerRunOptions
KubernetesOptions *k8s.KubernetesOptions
KubernetesOptions *k8s.KubernetesOptions DevopsOptions *devops.Options
DevopsOptions *devops.DevopsOptions SonarQubeOptions *sonarqube.Options
SonarQubeOptions *sonarqube.SonarQubeOptions ServiceMeshOptions *servicemesh.Options
ServiceMeshOptions *servicemesh.ServiceMeshOptions MySQLOptions *mysql.Options
MySQLOptions *mysql.MySQLOptions MonitoringOptions *prometheus.Options
MonitoringOptions *prometheus.PrometheusOptions S3Options *s3.Options
S3Options *s2is3.S3Options OpenPitrixOptions *openpitrix.Options
OpenPitrixOptions *openpitrix.OpenPitrixOptions LoggingOptions *esclient.Options
LoggingOptions *esclient.ElasticSearchOptions
} }
func NewServerRunOptions() *ServerRunOptions { func NewServerRunOptions() *ServerRunOptions {
@@ -41,7 +41,7 @@ func NewServerRunOptions() *ServerRunOptions {
ServiceMeshOptions: servicemesh.NewServiceMeshOptions(), ServiceMeshOptions: servicemesh.NewServiceMeshOptions(),
MySQLOptions: mysql.NewMySQLOptions(), MySQLOptions: mysql.NewMySQLOptions(),
MonitoringOptions: prometheus.NewPrometheusOptions(), MonitoringOptions: prometheus.NewPrometheusOptions(),
S3Options: s2is3.NewS3Options(), S3Options: s3.NewS3Options(),
OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(), OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(),
LoggingOptions: esclient.NewElasticSearchOptions(), LoggingOptions: esclient.NewElasticSearchOptions(),
} }
@@ -49,18 +49,17 @@ func NewServerRunOptions() *ServerRunOptions {
return &s return &s
} }
func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { func (s *ServerRunOptions) Flags(c *ServerRunOptions) (fss cliflag.NamedFlagSets) {
s.GenericServerRunOptions.AddFlags(fss.FlagSet("generic"), c.GenericServerRunOptions)
s.GenericServerRunOptions.AddFlags(fss.FlagSet("generic")) s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), c.KubernetesOptions)
s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes")) s.MySQLOptions.AddFlags(fss.FlagSet("mysql"), c.MySQLOptions)
s.MySQLOptions.AddFlags(fss.FlagSet("mysql")) s.DevopsOptions.AddFlags(fss.FlagSet("devops"), c.DevopsOptions)
s.DevopsOptions.AddFlags(fss.FlagSet("devops")) s.SonarQubeOptions.AddFlags(fss.FlagSet("sonarqube"), c.SonarQubeOptions)
s.SonarQubeOptions.AddFlags(fss.FlagSet("sonarqube")) s.S3Options.AddFlags(fss.FlagSet("s3"), c.S3Options)
s.S3Options.AddFlags(fss.FlagSet("s3")) s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix"), c.OpenPitrixOptions)
s.OpenPitrixOptions.AddFlags(fss.FlagSet("openpitrix")) s.ServiceMeshOptions.AddFlags(fss.FlagSet("servicemesh"), c.ServiceMeshOptions)
s.ServiceMeshOptions.AddFlags(fss.FlagSet("servicemesh")) s.MonitoringOptions.AddFlags(fss.FlagSet("monitoring"), c.MonitoringOptions)
s.MonitoringOptions.AddFlags(fss.FlagSet("monitoring")) s.LoggingOptions.AddFlags(fss.FlagSet("logging"), c.LoggingOptions)
s.LoggingOptions.AddFlags(fss.FlagSet("logging"))
fs := fss.FlagSet("klog") fs := fss.FlagSet("klog")
local := flag.NewFlagSet("klog", flag.ExitOnError) local := flag.NewFlagSet("klog", flag.ExitOnError)

View File

@@ -26,14 +26,18 @@ import (
cliflag "k8s.io/component-base/cli/flag" cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/cmd/ks-apiserver/app/options" "kubesphere.io/kubesphere/cmd/ks-apiserver/app/options"
"kubesphere.io/kubesphere/pkg/apiserver"
"kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/apiserver/servicemesh/tracing" "kubesphere.io/kubesphere/pkg/apiserver/servicemesh/tracing"
"kubesphere.io/kubesphere/pkg/informers" kinformers "kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/kapis" "kubesphere.io/kubesphere/pkg/kapis"
"kubesphere.io/kubesphere/pkg/server" "kubesphere.io/kubesphere/pkg/server"
apiserverconfig "kubesphere.io/kubesphere/pkg/server/config" apiserverconfig "kubesphere.io/kubesphere/pkg/server/config"
"kubesphere.io/kubesphere/pkg/server/filter" "kubesphere.io/kubesphere/pkg/server/filter"
"kubesphere.io/kubesphere/pkg/simple/client" "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/signals"
"kubesphere.io/kubesphere/pkg/utils/term" "kubesphere.io/kubesphere/pkg/utils/term"
"net/http" "net/http"
@@ -48,16 +52,6 @@ func NewAPIServerCommand() *cobra.Command {
The API Server services REST operations and provides the frontend to the The API Server services REST operations and provides the frontend to the
cluster's shared state through which all other components interact.`, cluster's shared state through which all other components interact.`,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
err := apiserverconfig.Load()
if err != nil {
return err
}
err = Complete(s)
if err != nil {
return err
}
if errs := s.Validate(); len(errs) != 0 { if errs := s.Validate(); len(errs) != 0 {
return utilerrors.NewAggregate(errs) return utilerrors.NewAggregate(errs)
} }
@@ -66,8 +60,10 @@ cluster's shared state through which all other components interact.`,
}, },
} }
configOptions := load()
fs := cmd.Flags() fs := cmd.Flags()
namedFlagSets := s.Flags() namedFlagSets := s.Flags(configOptions)
for _, f := range namedFlagSets.FlagSets { for _, f := range namedFlagSets.FlagSets {
fs.AddFlagSet(f) fs.AddFlagSet(f)
@@ -125,9 +121,13 @@ func initializeServicemeshConfig(s *options.ServerRunOptions) {
} }
// //
func CreateAPIServer(s *options.ServerRunOptions) error { func CreateAPIServer(s *options.ServerRunOptions, stopCh <-chan struct{}) error {
var err error var err error
deps := createDeps(s, stopCh)
apiserver := apiserver.New(deps)
container := runtime.Container container := runtime.Container
container.DoNotRecover(false) container.DoNotRecover(false)
container.Filter(filter.Logging) container.Filter(filter.Logging)
@@ -155,23 +155,35 @@ func CreateAPIServer(s *options.ServerRunOptions) error {
return err return err
} }
func CreateClientSet(conf *apiserverconfig.Config, stopCh <-chan struct{}) error { func createDeps(s *options.ServerRunOptions, stopCh <-chan struct{}) *apiserver.Dependencies {
csop := &client.ClientSetOptions{} deps := &apiserver.Dependencies{}
csop.SetDevopsOptions(conf.DevopsOptions). if s.KubernetesOptions == nil || s.KubernetesOptions.KubeConfig == "" {
SetSonarQubeOptions(conf.SonarQubeOptions). klog.Warning("kubeconfig not provided, will use in-cluster config")
SetKubernetesOptions(conf.KubernetesOptions). }
SetMySQLOptions(conf.MySQLOptions).
SetLdapOptions(conf.LdapOptions).
SetS3Options(conf.S3Options).
SetOpenPitrixOptions(conf.OpenPitrixOptions).
SetPrometheusOptions(conf.MonitoringOptions).
SetKubeSphereOptions(conf.KubeSphereOptions).
SetElasticSearchOptions(conf.LoggingOptions)
client.NewClientSetFactory(csop, stopCh) 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.NewOpenPitrixClient(s.OpenPitrixOptions)
if err != nil {
klog.Fatalf("error happened when initializing openpitrix client, %v", err)
}
}
return deps
return nil
} }
func WaitForResourceSync(stopCh <-chan struct{}) error { func WaitForResourceSync(stopCh <-chan struct{}) error {
@@ -196,7 +208,8 @@ func WaitForResourceSync(stopCh <-chan struct{}) error {
return false return false
} }
informerFactory := informers.SharedInformerFactory() 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 // resources we have to create informer first
k8sGVRs := []schema.GroupVersionResource{ k8sGVRs := []schema.GroupVersionResource{
@@ -234,7 +247,7 @@ func WaitForResourceSync(stopCh <-chan struct{}) error {
if !isResourceExists(gvr) { if !isResourceExists(gvr) {
klog.Warningf("resource %s not exists in the cluster", gvr) klog.Warningf("resource %s not exists in the cluster", gvr)
} else { } else {
_, err := informerFactory.ForResource(gvr) _, err := informerFactory.KubernetesSharedInformerFactory().ForResource(gvr)
if err != nil { if err != nil {
klog.Errorf("cannot create informer for %s", gvr) klog.Errorf("cannot create informer for %s", gvr)
return err return err
@@ -242,10 +255,10 @@ func WaitForResourceSync(stopCh <-chan struct{}) error {
} }
} }
informerFactory.Start(stopCh) informerFactory.KubernetesSharedInformerFactory().Start(stopCh)
informerFactory.WaitForCacheSync(stopCh) informerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(stopCh)
s2iInformerFactory := informers.S2iSharedInformerFactory() s2iInformerFactory := informerFactory.S2iSharedInformerFactory()
s2iGVRs := []schema.GroupVersionResource{ s2iGVRs := []schema.GroupVersionResource{
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"}, {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"},
@@ -267,7 +280,7 @@ func WaitForResourceSync(stopCh <-chan struct{}) error {
s2iInformerFactory.Start(stopCh) s2iInformerFactory.Start(stopCh)
s2iInformerFactory.WaitForCacheSync(stopCh) s2iInformerFactory.WaitForCacheSync(stopCh)
ksInformerFactory := informers.KsSharedInformerFactory() ksInformerFactory := informerFactory.KubeSphereSharedInformerFactory()
ksGVRs := []schema.GroupVersionResource{ ksGVRs := []schema.GroupVersionResource{
{Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"}, {Group: "tenant.kubesphere.io", Version: "v1alpha1", Resource: "workspaces"},
@@ -291,7 +304,7 @@ func WaitForResourceSync(stopCh <-chan struct{}) error {
ksInformerFactory.Start(stopCh) ksInformerFactory.Start(stopCh)
ksInformerFactory.WaitForCacheSync(stopCh) ksInformerFactory.WaitForCacheSync(stopCh)
appInformerFactory := informers.AppSharedInformerFactory() appInformerFactory := informerFactory.ApplicationSharedInformerFactory()
appGVRs := []schema.GroupVersionResource{ appGVRs := []schema.GroupVersionResource{
{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"}, {Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"},
@@ -317,36 +330,23 @@ func WaitForResourceSync(stopCh <-chan struct{}) error {
} }
// apply server run options to configuration // load options from config file
func Complete(s *options.ServerRunOptions) error { func load() *options.ServerRunOptions {
// loading configuration file
conf := apiserverconfig.Get() conf := apiserverconfig.Get()
conf.Apply(&apiserverconfig.Config{ return &options.ServerRunOptions{
MySQLOptions: s.MySQLOptions, KubernetesOptions: conf.KubernetesOptions,
DevopsOptions: s.DevopsOptions, DevopsOptions: conf.DevopsOptions,
SonarQubeOptions: s.SonarQubeOptions, SonarQubeOptions: conf.SonarQubeOptions,
KubernetesOptions: s.KubernetesOptions, ServiceMeshOptions: conf.ServiceMeshOptions,
ServiceMeshOptions: s.ServiceMeshOptions, MySQLOptions: conf.MySQLOptions,
MonitoringOptions: s.MonitoringOptions, MonitoringOptions: conf.MonitoringOptions,
S3Options: s.S3Options, S3Options: conf.S3Options,
OpenPitrixOptions: s.OpenPitrixOptions, OpenPitrixOptions: conf.OpenPitrixOptions,
LoggingOptions: s.LoggingOptions, LoggingOptions: conf.LoggingOptions,
})
*s = options.ServerRunOptions{
GenericServerRunOptions: s.GenericServerRunOptions,
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 return nil
} }

View File

@@ -22,10 +22,10 @@ import (
cliflag "k8s.io/component-base/cli/flag" cliflag "k8s.io/component-base/cli/flag"
"k8s.io/klog" "k8s.io/klog"
genericoptions "kubesphere.io/kubesphere/pkg/server/options" 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/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/ldap" "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"kubesphere.io/kubesphere/pkg/simple/client/mysql" "kubesphere.io/kubesphere/pkg/simple/client/mysql"
"kubesphere.io/kubesphere/pkg/simple/client/redis"
"strings" "strings"
"time" "time"
) )
@@ -33,9 +33,9 @@ import (
type ServerRunOptions struct { type ServerRunOptions struct {
GenericServerRunOptions *genericoptions.ServerRunOptions GenericServerRunOptions *genericoptions.ServerRunOptions
KubernetesOptions *k8s.KubernetesOptions KubernetesOptions *k8s.KubernetesOptions
LdapOptions *ldap.LdapOptions LdapOptions *ldap.Options
RedisOptions *redis.RedisOptions RedisOptions *cache.Options
MySQLOptions *mysql.MySQLOptions MySQLOptions *mysql.Options
AdminEmail string AdminEmail string
AdminPassword string AdminPassword string
TokenIdleTimeout time.Duration TokenIdleTimeout time.Duration
@@ -51,16 +51,16 @@ func NewServerRunOptions() *ServerRunOptions {
KubernetesOptions: k8s.NewKubernetesOptions(), KubernetesOptions: k8s.NewKubernetesOptions(),
LdapOptions: ldap.NewLdapOptions(), LdapOptions: ldap.NewLdapOptions(),
MySQLOptions: mysql.NewMySQLOptions(), MySQLOptions: mysql.NewMySQLOptions(),
RedisOptions: redis.NewRedisOptions(), RedisOptions: cache.NewRedisOptions(),
} }
return s return s
} }
func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) { func (s *ServerRunOptions) Flags(conf *ServerRunOptions) (fss cliflag.NamedFlagSets) {
fs := fss.FlagSet("generic") fs := fss.FlagSet("generic")
s.GenericServerRunOptions.AddFlags(fs) s.GenericServerRunOptions.AddFlags(fs, conf.GenericServerRunOptions)
fs.StringVar(&s.AdminEmail, "admin-email", "admin@kubesphere.io", "default administrator's email") 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.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.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\"")
@@ -69,10 +69,10 @@ func (s *ServerRunOptions) Flags() (fss cliflag.NamedFlagSets) {
fs.BoolVar(&s.EnableMultiLogin, "enable-multi-login", false, "allow one account to have multiple sessions") 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.") 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")) s.KubernetesOptions.AddFlags(fss.FlagSet("kubernetes"), conf.KubernetesOptions)
s.LdapOptions.AddFlags(fss.FlagSet("ldap")) s.LdapOptions.AddFlags(fss.FlagSet("ldap"), conf.LdapOptions)
s.RedisOptions.AddFlags(fss.FlagSet("redis")) s.RedisOptions.AddFlags(fss.FlagSet("redis"), conf.RedisOptions)
s.MySQLOptions.AddFlags(fss.FlagSet("mysql")) s.MySQLOptions.AddFlags(fss.FlagSet("mysql"), conf.MySQLOptions)
kfs := fss.FlagSet("klog") kfs := fss.FlagSet("klog")
local := flag.NewFlagSet("klog", flag.ExitOnError) local := flag.NewFlagSet("klog", flag.ExitOnError)

View File

@@ -53,11 +53,6 @@ cluster's shared state through which all other components interact.`,
return err return err
} }
err = Complete(s)
if err != nil {
return err
}
if errs := s.Validate(); len(errs) != 0 { if errs := s.Validate(); len(errs) != 0 {
return utilerrors.NewAggregate(errs) return utilerrors.NewAggregate(errs)
} }
@@ -66,8 +61,10 @@ cluster's shared state through which all other components interact.`,
}, },
} }
conf := loadFromFile()
fs := cmd.Flags() fs := cmd.Flags()
namedFlagSets := s.Flags() namedFlagSets := s.Flags(conf)
for _, f := range namedFlagSets.FlagSets { for _, f := range namedFlagSets.FlagSets {
fs.AddFlagSet(f) fs.AddFlagSet(f)
@@ -122,22 +119,20 @@ func Run(s *options.ServerRunOptions, stopChan <-chan struct{}) error {
return err return err
} }
func Complete(s *options.ServerRunOptions) error { func loadFromFile() *options.ServerRunOptions {
err := apiserverconfig.Load()
if err != nil {
klog.Fatal(err)
}
conf := apiserverconfig.Get() conf := apiserverconfig.Get()
conf.Apply(&apiserverconfig.Config{ return &options.ServerRunOptions{
KubernetesOptions: s.KubernetesOptions, KubernetesOptions: conf.KubernetesOptions,
LdapOptions: s.LdapOptions, LdapOptions: conf.LdapOptions,
RedisOptions: s.RedisOptions, RedisOptions: conf.RedisOptions,
MySQLOptions: s.MySQLOptions, MySQLOptions: conf.MySQLOptions,
}) }
s.KubernetesOptions = conf.KubernetesOptions
s.LdapOptions = conf.LdapOptions
s.RedisOptions = conf.RedisOptions
s.MySQLOptions = conf.MySQLOptions
return nil
} }
func waitForResourceSync(stopCh <-chan struct{}) { func waitForResourceSync(stopCh <-chan struct{}) {

17
go.mod
View File

@@ -40,6 +40,7 @@ require (
github.com/gocraft/dbr v0.0.0-20180507214907-a0fd650918f6 github.com/gocraft/dbr v0.0.0-20180507214907-a0fd650918f6
github.com/golang/example v0.0.0-20170904185048-46695d81d1fa github.com/golang/example v0.0.0-20170904185048-46695d81d1fa
github.com/golang/protobuf v1.3.2 github.com/golang/protobuf v1.3.2
github.com/google/go-cmp v0.3.0
github.com/google/go-querystring v1.0.0 // indirect github.com/google/go-querystring v1.0.0 // indirect
github.com/google/uuid v1.1.1 github.com/google/uuid v1.1.1
github.com/gophercloud/gophercloud v0.3.0 // indirect github.com/gophercloud/gophercloud v0.3.0 // indirect
@@ -63,8 +64,8 @@ require (
github.com/mholt/certmagic v0.5.1 // indirect github.com/mholt/certmagic v0.5.1 // indirect
github.com/miekg/dns v1.1.9 // indirect github.com/miekg/dns v1.1.9 // indirect
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c // indirect
github.com/onsi/ginkgo v1.8.0 github.com/onsi/ginkgo v1.10.1
github.com/onsi/gomega v1.5.0 github.com/onsi/gomega v1.7.0
github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/go-digest v1.0.0-rc1
github.com/opencontainers/image-spec v1.0.1 // indirect github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/openshift/api v3.9.0+incompatible // indirect github.com/openshift/api v3.9.0+incompatible // indirect
@@ -87,16 +88,16 @@ require (
gopkg.in/yaml.v2 v2.2.4 gopkg.in/yaml.v2 v2.2.4
istio.io/api v0.0.0-20191111210003-35e06ef8d838 istio.io/api v0.0.0-20191111210003-35e06ef8d838
istio.io/client-go v0.0.0-20191113122552-9bd0ba57c3d2 istio.io/client-go v0.0.0-20191113122552-9bd0ba57c3d2
k8s.io/api v0.0.0-20191114100352-16d7abae0d2a k8s.io/api v0.17.0
k8s.io/apiextensions-apiserver v0.0.0-20191114105449-027877536833 k8s.io/apiextensions-apiserver v0.0.0-20191114105449-027877536833
k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb k8s.io/apimachinery v0.17.0
k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682 k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 k8s.io/client-go v0.17.0
k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 k8s.io/code-generator v0.17.0
k8s.io/component-base v0.0.0-20191114102325-35a9586014f7 k8s.io/component-base v0.17.0
k8s.io/klog v1.0.0 k8s.io/klog v1.0.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f // indirect k8s.io/kubectl v0.17.0
kubesphere.io/im v0.1.0 // indirect kubesphere.io/im v0.1.0 // indirect
openpitrix.io/iam v0.1.0 // indirect openpitrix.io/iam v0.1.0 // indirect
openpitrix.io/openpitrix v0.4.1-0.20190920134345-4d2be6e4965c openpitrix.io/openpitrix v0.4.1-0.20190920134345-4d2be6e4965c

27
go.sum
View File

@@ -18,6 +18,8 @@ github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VY
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU=
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc= github.com/Microsoft/go-winio v0.4.12 h1:xAfWHN1IrQ0NJ9TBC0KBZoqLjzDTr1ML+4MywiUOryc=
@@ -60,6 +62,8 @@ github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dR
github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 h1:7aWHqerlJ41y6FOsEUvknqgXnGmJyJSbjhAWq5pO4F8=
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
@@ -77,6 +81,7 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= github.com/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ=
github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc= github.com/denisenkom/go-mssqldb v0.0.0-20190204142019-df6d76eb9289/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
@@ -115,6 +120,8 @@ github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3
github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
@@ -191,6 +198,9 @@ github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golangplus/bytes v0.0.0-20160111154220-45c989fe5450/go.mod h1:Bk6SMAONeMXrxql8uvOKuAZSu8aM5RUGv+1C6IJaEho=
github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkYFkPcDKwRXegd+iM6E7matEszMG5HhwytU8=
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY= github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
@@ -213,6 +223,7 @@ github.com/gorilla/mux v1.7.1 h1:Dw4jY2nghMMRsh1ol8dv1axHkDwMQK2DHerMNJsIpJU=
github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
@@ -285,6 +296,9 @@ github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0= github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4= github.com/lucas-clemente/quic-go v0.11.1 h1:zasajC848Dqq/+WqfqBCkmPw+YHNe1MBts/z7y7nXf4=
github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw= github.com/lucas-clemente/quic-go v0.11.1/go.mod h1:PpMmPfPKO9nKJ/psF49ESTAGQSdfXxlg1otPbEB2nOw=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY= github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
@@ -309,6 +323,8 @@ github.com/miekg/dns v1.1.9 h1:OIdC9wT96RzuZMf2PfKRhFgsStHUUBZLM/lo1LqiM9E=
github.com/miekg/dns v1.1.9/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.9/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
@@ -343,6 +359,7 @@ github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWo
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
@@ -416,6 +433,7 @@ github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/handysort v0.0.0-20150421192137-fb3537ed64a1/go.mod h1:QcJo0QPSfTONNIgpN5RA8prR7fF8nkF6cTWTcNerRO8=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk= go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
@@ -517,6 +535,8 @@ k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb h1:ZUNsbuPdXWrj0rZziRfCWc
k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ= k8s.io/apimachinery v0.0.0-20191028221656-72ed19daf4bb/go.mod h1:llRdnznGEAqC3DcNm6yEj472xaFVfLM7hnYofMb12tQ=
k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682 h1:+FvAOv/4JyYgZanQI8h+UW9FCmLzyEz7EZunuET6p5g= k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682 h1:+FvAOv/4JyYgZanQI8h+UW9FCmLzyEz7EZunuET6p5g=
k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682/go.mod h1:Idob8Va6/sMX5SmwPLsU0pdvFlkwxuJ5x+fXMG8NbKE= k8s.io/apiserver v0.0.0-20191114103151-9ca1dc586682/go.mod h1:Idob8Va6/sMX5SmwPLsU0pdvFlkwxuJ5x+fXMG8NbKE=
k8s.io/cli-runtime v0.17.0 h1:XEuStbJBHCQlEKFyTQmceDKEWOSYHZkcYWKp3SsQ9Hk=
k8s.io/cli-runtime v0.17.0/go.mod h1:1E5iQpMODZq2lMWLUJELwRu2MLWIzwvMgDBpn3Y81Qo=
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 h1:07mhG/2oEoo3N+sHVOo0L9PJ/qvbk3N5n2dj8IWefnQ= k8s.io/client-go v0.0.0-20191114101535-6c5935290e33 h1:07mhG/2oEoo3N+sHVOo0L9PJ/qvbk3N5n2dj8IWefnQ=
k8s.io/client-go v0.0.0-20191114101535-6c5935290e33/go.mod h1:4L/zQOBkEf4pArQJ+CMk1/5xjA30B5oyWv+Bzb44DOw= k8s.io/client-go v0.0.0-20191114101535-6c5935290e33/go.mod h1:4L/zQOBkEf4pArQJ+CMk1/5xjA30B5oyWv+Bzb44DOw=
k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 h1:NMYlxaF7rYQJk2E2IyrUhaX81zX24+dmoZdkPw0gJqI= k8s.io/code-generator v0.0.0-20191004115455-8e001e5d1894 h1:NMYlxaF7rYQJk2E2IyrUhaX81zX24+dmoZdkPw0gJqI=
@@ -529,6 +549,9 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU=
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kubectl v0.17.0 h1:xD4EWlL+epc/JTO1gvSjmV9yiYF0Z2wiHK2DIek6URY=
k8s.io/kubectl v0.17.0/go.mod h1:jIPrUAW656Vzn9wZCCe0PC+oTcu56u2HgFD21Xbfk1s=
k8s.io/metrics v0.17.0/go.mod h1:EH1D3YAwN6d7bMelrElnLhLg72l/ERStyv2SIQVt6Do=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f h1:GiPwtSzdP43eI1hpPCbROQCCIgCuiMMNF8YUVLF3vJo=
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
kubesphere.io/application v0.0.0-20190404151855-67ae7f915d4e/go.mod h1:NhUQ0ZUdFz8NTQ+SvQG0JUKAn+q71v3TPExjsjRPIZI= kubesphere.io/application v0.0.0-20190404151855-67ae7f915d4e/go.mod h1:NhUQ0ZUdFz8NTQ+SvQG0JUKAn+q71v3TPExjsjRPIZI=
@@ -549,9 +572,13 @@ sigs.k8s.io/controller-runtime v0.4.0 h1:wATM6/m+3w8lj8FXNaO6Fs/rq/vqoOjO1Q116Z9
sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns= sigs.k8s.io/controller-runtime v0.4.0/go.mod h1:ApC79lpY3PHW9xj/w9pj+lYkLgwAAUZwfXkME1Lajns=
sigs.k8s.io/controller-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA= sigs.k8s.io/controller-tools v0.2.4 h1:la1h46EzElvWefWLqfsXrnsO3lZjpkI0asTpX6h8PLA=
sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA= sigs.k8s.io/controller-tools v0.2.4/go.mod h1:m/ztfQNocGYBgTTCmFdnK94uVvgxeZeE3LtJvd/jIzA=
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ= sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca h1:6dsH6AYQWbyZmtttJNe8Gq1cXOeS1BdV3eW37zHilAQ=
sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA= sigs.k8s.io/structured-merge-diff v0.0.0-20190817042607-6149e4549fca/go.mod h1:IIgPezJWb76P0hotTxzDbWsMYB8APh18qZnxkomBpxA=
sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH+UQM= sigs.k8s.io/testing_frameworks v0.1.2 h1:vK0+tvjF0BZ/RYFeZ1E6BYBwHJJXhjuZ3TdsEKH+UQM=
sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w= sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc h1:MksmcCZQWAQJCTA5T0jgI/0sJ51AVm4Z41MrmfczEoc=
vbom.ml/util v0.0.0-20160121211510-db5cfe13f5cc/go.mod h1:so/NYdZXCz+E3ZpW0uAoCj6uzU2+8OWDFv/HxUSs7kI=

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
set -e set -e
GV="network:v1alpha1 servicemesh:v1alpha2 tenant:v1alpha1 devops:v1alpha1" GV="network:v1alpha1 servicemesh:v1alpha2 tenant:v1alpha1 devops:v1alpha1 logging:v1alpha2"
rm -rf ./pkg/client rm -rf ./pkg/client
./hack/generate_group.sh "client,lister,informer" kubesphere.io/kubesphere/pkg/client kubesphere.io/kubesphere/pkg/apis "$GV" --output-base=./ -h "$PWD/hack/boilerplate.go.txt" ./hack/generate_group.sh "client,lister,informer" kubesphere.io/kubesphere/pkg/client kubesphere.io/kubesphere/pkg/apis "$GV" --output-base=./ -h "$PWD/hack/boilerplate.go.txt"

View File

@@ -0,0 +1 @@
package resource

View File

@@ -0,0 +1,29 @@
package v1alpha2
import "time"
// ComponentStatus represents system component status.
type ComponentStatus struct {
Name string `json:"name" description:"component name"`
Namespace string `json:"namespace" description:"the name of the namespace"`
SelfLink string `json:"selfLink" description:"self link"`
Label interface{} `json:"label" description:"labels"`
StartedAt time.Time `json:"startedAt" description:"started time"`
TotalBackends int `json:"totalBackends" description:"the total replicas of each backend system component"`
HealthyBackends int `json:"healthyBackends" description:"the number of healthy backend components"`
}
// NodeStatus assembles cluster nodes status, simply wrap unhealthy and total nodes.
type NodeStatus struct {
// total nodes of cluster, including master nodes
TotalNodes int `json:"totalNodes" description:"total number of nodes"`
// healthy nodes means nodes whose state is NodeReady
HealthyNodes int `json:"healthyNodes" description:"the number of healthy nodes"`
}
//
type HealthStatus struct {
KubeSphereComponents []ComponentStatus `json:"kubesphereStatus" description:"kubesphere components status"`
NodeStatus NodeStatus `json:"nodeStatus" description:"nodes status"`
}

170
pkg/api/types.go Normal file
View File

@@ -0,0 +1,170 @@
package api
import (
"github.com/emicklei/go-restful"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"net/http"
)
type ListResult struct {
Items []interface{} `json:"items,omitempty"`
TotalItems int `json:"totalItems,omitempty"`
}
type ResourceQuota struct {
Namespace string `json:"namespace" description:"namespace"`
Data corev1.ResourceQuotaStatus `json:"data" description:"resource quota status"`
}
type NamespacedResourceQuota struct {
Namespace string `json:"namespace,omitempty"`
Data struct {
corev1.ResourceQuotaStatus
// quota left status, do the math on the side, cause it's
// a lot easier with go-client library
Left corev1.ResourceList `json:"left,omitempty"`
} `json:"data,omitempty"`
}
type Router struct {
RouterType string `json:"type"`
Annotations map[string]string `json:"annotations"`
}
type GitCredential struct {
RemoteUrl string `json:"remoteUrl" description:"git server url"`
SecretRef *corev1.SecretReference `json:"secretRef,omitempty" description:"auth secret reference"`
}
type RegistryCredential struct {
Username string `json:"username" description:"username"`
Password string `json:"password" description:"password"`
ServerHost string `json:"serverhost" description:"registry server host"`
}
type Workloads struct {
Namespace string `json:"namespace" description:"the name of the namespace"`
Count map[string]int `json:"data" description:"the number of unhealthy workloads"`
Items map[string]interface{} `json:"items,omitempty" description:"unhealthy workloads"`
}
type ClientType string
const (
ClientKubernetes ClientType = "Kubernetes"
ClientKubeSphere ClientType = "Kubesphere"
ClientIstio ClientType = "Istio"
ClientS2i ClientType = "S2i"
ClientApplication ClientType = "Application"
StatusOK = "ok"
)
var SupportedGroupVersionResources = map[ClientType][]schema.GroupVersionResource{
// all supported kubernetes api objects
ClientKubernetes: {
{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"},
},
// all supported kubesphere api objects
ClientKubeSphere: {
{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"},
},
// all supported istio api objects
ClientIstio: {},
// all supported s2i api objects
// TODO: move s2i clientset into kubesphere
ClientS2i: {
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuildertemplates"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2iruns"},
{Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"},
},
// kubernetes-sigs application api objects
ClientApplication: {
{Group: "app.k8s.io", Version: "v1beta1", Resource: "applications"},
},
}
// List of all resource kinds supported by the UI.
const (
ResourceKindConfigMap = "configmaps"
ResourceKindDaemonSet = "daemonsets"
ResourceKindDeployment = "deployments"
ResourceKindEvent = "events"
ResourceKindHorizontalPodAutoscaler = "horizontalpodautoscalers"
ResourceKindIngress = "ingresses"
ResourceKindJob = "jobs"
ResourceKindCronJob = "cronjobs"
ResourceKindLimitRange = "limitranges"
ResourceKindNamespace = "namespaces"
ResourceKindNode = "nodes"
ResourceKindPersistentVolumeClaim = "persistentvolumeclaims"
ResourceKindPersistentVolume = "persistentvolumes"
ResourceKindCustomResourceDefinition = "customresourcedefinitions"
ResourceKindPod = "pods"
ResourceKindReplicaSet = "replicasets"
ResourceKindResourceQuota = "resourcequota"
ResourceKindSecret = "secrets"
ResourceKindService = "services"
ResourceKindStatefulSet = "statefulsets"
ResourceKindStorageClass = "storageclasses"
ResourceKindClusterRole = "clusterroles"
ResourceKindClusterRoleBinding = "clusterrolebindings"
ResourceKindRole = "roles"
ResourceKindRoleBinding = "rolebindings"
ResourceKindWorkspace = "workspaces"
ResourceKindS2iBinary = "s2ibinaries"
ResourceKindStrategy = "strategy"
ResourceKindServicePolicy = "servicepolicies"
ResourceKindS2iBuilderTemplate = "s2ibuildertemplates"
ResourceKindeS2iRun = "s2iruns"
ResourceKindS2iBuilder = "s2ibuilders"
ResourceKindApplication = "applications"
)
func HandleInternalError(response *restful.Response, err error) {
statusCode := http.StatusInternalServerError
response.WriteError(statusCode, err)
}
func HandleBadRequest(response *restful.Response, err error) {
}

View File

@@ -25,7 +25,7 @@ import (
"k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal"
"kubesphere.io/kubesphere/pkg/simple/client/redis" "kubesphere.io/kubesphere/pkg/simple/client/cache"
"log" "log"
"net/http" "net/http"
"strconv" "strconv"
@@ -44,9 +44,9 @@ type Auth struct {
type Rule struct { type Rule struct {
Secret []byte Secret []byte
Path string Path string
RedisOptions *redis.RedisOptions RedisOptions *cache.Options
TokenIdleTimeout time.Duration TokenIdleTimeout time.Duration
RedisClient *redis.RedisClient RedisClient cache.Interface
ExclusionRules []internal.ExclusionRule ExclusionRules []internal.ExclusionRule
} }
@@ -194,15 +194,15 @@ func (h Auth) Validate(uToken string) (*jwt.Token, error) {
tokenKey := fmt.Sprintf("kubesphere:users:%s:token:%s", username, uToken) tokenKey := fmt.Sprintf("kubesphere:users:%s:token:%s", username, uToken)
exist, err := h.Rule.RedisClient.Redis().Exists(tokenKey).Result() exist, err := h.Rule.RedisClient.Exists(tokenKey)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
} }
if exist == 1 { if exist {
// reset expiration time if token exist // reset expiration time if token exist
h.Rule.RedisClient.Redis().Expire(tokenKey, h.Rule.TokenIdleTimeout) h.Rule.RedisClient.Expire(tokenKey, h.Rule.TokenIdleTimeout)
return token, nil return token, nil
} else { } else {
return nil, errors.New("illegal token") return nil, errors.New("illegal token")

View File

@@ -20,7 +20,7 @@ package authenticate
import ( import (
"fmt" "fmt"
"kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal"
"kubesphere.io/kubesphere/pkg/simple/client/redis" "kubesphere.io/kubesphere/pkg/simple/client/cache"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
"time" "time"
@@ -36,8 +36,10 @@ func Setup(c *caddy.Controller) error {
return err return err
} }
stopCh := make(chan struct{})
c.OnStartup(func() error { c.OnStartup(func() error {
rule.RedisClient, err = redis.NewRedisClient(rule.RedisOptions, nil) rule.RedisClient, err = cache.NewRedisClient(rule.RedisOptions, stopCh)
// ensure redis is connected when startup // ensure redis is connected when startup
if err != nil { if err != nil {
return err return err
@@ -47,7 +49,8 @@ func Setup(c *caddy.Controller) error {
}) })
c.OnShutdown(func() error { c.OnShutdown(func() error {
return rule.RedisClient.Redis().Close() close(stopCh)
return nil
}) })
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
@@ -96,7 +99,7 @@ func parse(c *caddy.Controller) (*Rule, error) {
return nil, c.ArgErr() return nil, c.ArgErr()
} }
options := &redis.RedisOptions{RedisURL: c.Val()} options := &cache.Options{RedisURL: c.Val()}
if err := options.Validate(); len(err) > 0 { if err := options.Validate(); len(err) > 0 {
return nil, c.ArgErr() return nil, c.ArgErr()

View File

@@ -23,7 +23,9 @@ import (
"fmt" "fmt"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/request" "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/k8sutil"
"log" "log"
"net/http" "net/http"
@@ -34,21 +36,22 @@ import (
k8serr "k8s.io/apimachinery/pkg/api/errors" k8serr "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
) )
type Authentication struct { type Authentication struct {
Rule *Rule Rule *Rule
Next httpserver.Handler Next httpserver.Handler
informerFactory informers.SharedInformerFactory
} }
type Rule struct { type Rule struct {
Path string Path string
ExclusionRules []internal.ExclusionRule KubernetesOptions *k8s.KubernetesOptions
ExclusionRules []internal.ExclusionRule
} }
func (c Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) { func (c *Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request) (int, error) {
if httpserver.Path(r.URL.Path).Matches(c.Rule.Path) { if httpserver.Path(r.URL.Path).Matches(c.Rule.Path) {
@@ -65,7 +68,7 @@ func (c Authentication) ServeHTTP(w http.ResponseWriter, r *http.Request) (int,
return c.Next.ServeHTTP(w, r) return c.Next.ServeHTTP(w, r)
} }
permitted, err := permissionValidate(attrs) permitted, err := c.permissionValidate(attrs)
if err != nil { if err != nil {
return http.StatusInternalServerError, err return http.StatusInternalServerError, err
@@ -88,13 +91,13 @@ func handleForbidden(w http.ResponseWriter, err error) int {
return http.StatusForbidden return http.StatusForbidden
} }
func permissionValidate(attrs authorizer.Attributes) (bool, error) { func (c *Authentication) permissionValidate(attrs authorizer.Attributes) (bool, error) {
if attrs.GetResource() == "users" && attrs.GetUser().GetName() == attrs.GetName() { if attrs.GetResource() == "users" && attrs.GetUser().GetName() == attrs.GetName() {
return true, nil return true, nil
} }
permitted, err := clusterRoleValidate(attrs) permitted, err := c.clusterRoleValidate(attrs)
if err != nil { if err != nil {
log.Println("lister error", err) log.Println("lister error", err)
@@ -106,7 +109,7 @@ func permissionValidate(attrs authorizer.Attributes) (bool, error) {
} }
if attrs.GetNamespace() != "" { if attrs.GetNamespace() != "" {
permitted, err = roleValidate(attrs) permitted, err = c.roleValidate(attrs)
if err != nil { if err != nil {
log.Println("lister error", err) log.Println("lister error", err)
@@ -121,9 +124,9 @@ func permissionValidate(attrs authorizer.Attributes) (bool, error) {
return false, nil return false, nil
} }
func roleValidate(attrs authorizer.Attributes) (bool, error) { func (c *Authentication) roleValidate(attrs authorizer.Attributes) (bool, error) {
roleBindingLister := informers.SharedInformerFactory().Rbac().V1().RoleBindings().Lister() roleBindingLister := c.informerFactory.Rbac().V1().RoleBindings().Lister()
roleLister := informers.SharedInformerFactory().Rbac().V1().Roles().Lister() roleLister := c.informerFactory.Rbac().V1().Roles().Lister()
roleBindings, err := roleBindingLister.RoleBindings(attrs.GetNamespace()).List(labels.Everything()) roleBindings, err := roleBindingLister.RoleBindings(attrs.GetNamespace()).List(labels.Everything())
if err != nil { if err != nil {
@@ -158,10 +161,10 @@ func roleValidate(attrs authorizer.Attributes) (bool, error) {
return false, nil return false, nil
} }
func clusterRoleValidate(attrs authorizer.Attributes) (bool, error) { func (c *Authentication) clusterRoleValidate(attrs authorizer.Attributes) (bool, error) {
clusterRoleBindingLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister() clusterRoleBindingLister := c.informerFactory.Rbac().V1().ClusterRoleBindings().Lister()
clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything()) clusterRoleBindings, err := clusterRoleBindingLister.List(labels.Everything())
clusterRoleLister := informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister() clusterRoleLister := c.informerFactory.Rbac().V1().ClusterRoles().Lister()
if err != nil { if err != nil {
return false, err return false, err
} }

View File

@@ -21,7 +21,9 @@ import (
"fmt" "fmt"
"github.com/mholt/caddy" "github.com/mholt/caddy"
"github.com/mholt/caddy/caddyhttp/httpserver" "github.com/mholt/caddy/caddyhttp/httpserver"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal" "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/internal"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/informers"
@@ -31,19 +33,28 @@ import (
func Setup(c *caddy.Controller) error { func Setup(c *caddy.Controller) error {
rule, err := parse(c) rule, err := parse(c)
if err != nil { if err != nil {
return err return err
} }
if rule.KubernetesOptions == nil && rule.KubernetesOptions.KubeConfig == "" {
klog.Warning("no kubeconfig provided, will use in cluster config, this may not work")
}
kubeClient, err := k8s.NewKubernetesClient(rule.KubernetesOptions)
if err != nil {
return err
}
informerFactory := informers.NewInformerFactories(kubeClient.Kubernetes(), nil, nil, nil)
stopChan := make(chan struct{}, 0) stopChan := make(chan struct{}, 0)
c.OnStartup(func() error { c.OnStartup(func() error {
informerFactory := informers.SharedInformerFactory() informerFactory.KubernetesSharedInformerFactory().Rbac().V1().Roles().Lister()
informerFactory.Rbac().V1().Roles().Lister() informerFactory.KubernetesSharedInformerFactory().Rbac().V1().RoleBindings().Lister()
informerFactory.Rbac().V1().RoleBindings().Lister() informerFactory.KubernetesSharedInformerFactory().Rbac().V1().ClusterRoles().Lister()
informerFactory.Rbac().V1().ClusterRoles().Lister() informerFactory.KubernetesSharedInformerFactory().Rbac().V1().ClusterRoleBindings().Lister()
informerFactory.Rbac().V1().ClusterRoleBindings().Lister() informerFactory.KubernetesSharedInformerFactory().Start(stopChan)
informerFactory.Start(stopChan) informerFactory.KubernetesSharedInformerFactory().WaitForCacheSync(stopChan)
informerFactory.WaitForCacheSync(stopChan)
fmt.Println("Authentication middleware is initiated") fmt.Println("Authentication middleware is initiated")
return nil return nil
}) })
@@ -54,7 +65,7 @@ func Setup(c *caddy.Controller) error {
}) })
httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler { httpserver.GetConfig(c).AddMiddleware(func(next httpserver.Handler) httpserver.Handler {
return &Authentication{Next: next, Rule: rule} return &Authentication{Next: next, Rule: rule, informerFactory: informerFactory.KubernetesSharedInformerFactory()}
}) })
return nil return nil
} }

View File

@@ -0,0 +1,8 @@
package apis
import "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
func init() {
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
AddToSchemes = append(AddToSchemes, v1alpha2.SchemeBuilder.AddToScheme)
}

View File

@@ -56,7 +56,7 @@ func (in *S2iBinary) DeepCopyObject() runtime.Object {
func (in *S2iBinaryList) DeepCopyInto(out *S2iBinaryList) { func (in *S2iBinaryList) DeepCopyInto(out *S2iBinaryList) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil { if in.Items != nil {
in, out := &in.Items, &out.Items in, out := &in.Items, &out.Items
*out = make([]S2iBinary, len(*in)) *out = make([]S2iBinary, len(*in))

View File

@@ -0,0 +1 @@
package logging

View File

@@ -0,0 +1,23 @@
/*
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 v1alpha2 contains API Schema definitions for the servicemesh v1alpha2 API group
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/logging
// +k8s:defaulter-gen=TypeMeta
// +groupName=logging.kubesphere.io
package v1alpha2

View File

@@ -0,0 +1,71 @@
package v1alpha2
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type FluentBit struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
Spec FluentBitSpec `json:"spec"`
Status FluentBitStatus `json:"status,omitempty"`
}
// FluentBitSpec holds the spec for the operator
type FluentBitSpec struct {
Service []Plugin `json:"service"`
Input []Plugin `json:"input"`
Filter []Plugin `json:"filter"`
Output []Plugin `json:"output"`
Settings []Plugin `json:"settings"`
}
// FluentBitStatus holds the status info for the operator
type FluentBitStatus struct {
// Fill me
}
// Plugin struct for fluent-bit plugins
type Plugin struct {
Type string `json:"type" description:"output plugin type, eg. fluentbit-output-es"`
Name string `json:"name" description:"output plugin name, eg. fluentbit-output-es"`
Parameters []Parameter `json:"parameters" description:"output plugin configuration parameters"`
}
// Fluent-bit output plugins
type OutputPlugin struct {
Plugin
Id string `json:"id,omitempty" description:"output uuid"`
Enable bool `json:"enable" description:"active status, one of true, false"`
Updatetime *metav1.Time `json:"updatetime,omitempty" description:"last updatetime"`
}
// Parameter generic parameter type to handle values from different sources
type Parameter struct {
Name string `json:"name" description:"configuration parameter key, eg. Name. refer to Fluent bit's Output Plugins Section for more configuration parameters."`
ValueFrom *ValueFrom `json:"valueFrom,omitempty"`
Value string `json:"value" description:"configuration parameter value, eg. es. refer to Fluent bit's Output Plugins Section for more configuration parameters."`
}
// ValueFrom generic type to determine value origin
type ValueFrom struct {
SecretKeyRef KubernetesSecret `json:"secretKeyRef"`
}
// KubernetesSecret is a ValueFrom type
type KubernetesSecret struct {
Name string `json:"name"`
Key string `json:"key"`
Namespace string `json:"namespace"`
}
// FluentBitList auto generated by the sdk
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type FluentBitList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []FluentBit `json:"items"`
}

View File

@@ -0,0 +1,44 @@
/*
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 contains API Schema definitions for the tenant v1alpha1 API group
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=kubesphere.io/kubesphere/pkg/apis/logging
// +k8s:defaulter-gen=TypeMeta
// +groupName=logging.kubesphere.io
package v1alpha2
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/runtime/scheme"
)
var (
// SchemeGroupVersion is group version used to register these objects
SchemeGroupVersion = schema.GroupVersion{Group: "logging.kubesphere.io", Version: "v1alpha2"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
// AddToScheme is required by pkg/client/...
AddToScheme = SchemeBuilder.AddToScheme
)
// Resource is required by pkg/client/listers/...
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}

View File

@@ -0,0 +1,251 @@
// +build !ignore_autogenerated
/*
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 deepcopy-gen. DO NOT EDIT.
package v1alpha2
import (
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 *FluentBit) DeepCopyInto(out *FluentBit) {
*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 FluentBit.
func (in *FluentBit) DeepCopy() *FluentBit {
if in == nil {
return nil
}
out := new(FluentBit)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FluentBit) 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 *FluentBitList) DeepCopyInto(out *FluentBitList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]FluentBit, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitList.
func (in *FluentBitList) DeepCopy() *FluentBitList {
if in == nil {
return nil
}
out := new(FluentBitList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *FluentBitList) 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 *FluentBitSpec) DeepCopyInto(out *FluentBitSpec) {
*out = *in
if in.Service != nil {
in, out := &in.Service, &out.Service
*out = make([]Plugin, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Input != nil {
in, out := &in.Input, &out.Input
*out = make([]Plugin, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Filter != nil {
in, out := &in.Filter, &out.Filter
*out = make([]Plugin, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Output != nil {
in, out := &in.Output, &out.Output
*out = make([]Plugin, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.Settings != nil {
in, out := &in.Settings, &out.Settings
*out = make([]Plugin, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitSpec.
func (in *FluentBitSpec) DeepCopy() *FluentBitSpec {
if in == nil {
return nil
}
out := new(FluentBitSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *FluentBitStatus) DeepCopyInto(out *FluentBitStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FluentBitStatus.
func (in *FluentBitStatus) DeepCopy() *FluentBitStatus {
if in == nil {
return nil
}
out := new(FluentBitStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesSecret) DeepCopyInto(out *KubernetesSecret) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KubernetesSecret.
func (in *KubernetesSecret) DeepCopy() *KubernetesSecret {
if in == nil {
return nil
}
out := new(KubernetesSecret)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OutputPlugin) DeepCopyInto(out *OutputPlugin) {
*out = *in
in.Plugin.DeepCopyInto(&out.Plugin)
if in.Updatetime != nil {
in, out := &in.Updatetime, &out.Updatetime
*out = (*in).DeepCopy()
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OutputPlugin.
func (in *OutputPlugin) DeepCopy() *OutputPlugin {
if in == nil {
return nil
}
out := new(OutputPlugin)
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.ValueFrom != nil {
in, out := &in.ValueFrom, &out.ValueFrom
*out = new(ValueFrom)
**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 *Plugin) DeepCopyInto(out *Plugin) {
*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 Plugin.
func (in *Plugin) DeepCopy() *Plugin {
if in == nil {
return nil
}
out := new(Plugin)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ValueFrom) DeepCopyInto(out *ValueFrom) {
*out = *in
out.SecretKeyRef = in.SecretKeyRef
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ValueFrom.
func (in *ValueFrom) DeepCopy() *ValueFrom {
if in == nil {
return nil
}
out := new(ValueFrom)
in.DeepCopyInto(out)
return out
}

View File

@@ -168,7 +168,7 @@ func (in *NamespaceNetworkPolicy) DeepCopyObject() runtime.Object {
func (in *NamespaceNetworkPolicyList) DeepCopyInto(out *NamespaceNetworkPolicyList) { func (in *NamespaceNetworkPolicyList) DeepCopyInto(out *NamespaceNetworkPolicyList) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil { if in.Items != nil {
in, out := &in.Items, &out.Items in, out := &in.Items, &out.Items
*out = make([]NamespaceNetworkPolicy, len(*in)) *out = make([]NamespaceNetworkPolicy, len(*in))
@@ -398,7 +398,7 @@ func (in *WorkspaceNetworkPolicyIngressRule) DeepCopy() *WorkspaceNetworkPolicyI
func (in *WorkspaceNetworkPolicyList) DeepCopyInto(out *WorkspaceNetworkPolicyList) { func (in *WorkspaceNetworkPolicyList) DeepCopyInto(out *WorkspaceNetworkPolicyList) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil { if in.Items != nil {
in, out := &in.Items, &out.Items in, out := &in.Items, &out.Items
*out = make([]WorkspaceNetworkPolicy, len(*in)) *out = make([]WorkspaceNetworkPolicy, len(*in))

View File

@@ -93,7 +93,7 @@ func (in *ServicePolicyCondition) DeepCopy() *ServicePolicyCondition {
func (in *ServicePolicyList) DeepCopyInto(out *ServicePolicyList) { func (in *ServicePolicyList) DeepCopyInto(out *ServicePolicyList) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil { if in.Items != nil {
in, out := &in.Items, &out.Items in, out := &in.Items, &out.Items
*out = make([]ServicePolicy, len(*in)) *out = make([]ServicePolicy, len(*in))
@@ -225,7 +225,7 @@ func (in *StrategyCondition) DeepCopy() *StrategyCondition {
func (in *StrategyList) DeepCopyInto(out *StrategyList) { func (in *StrategyList) DeepCopyInto(out *StrategyList) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil { if in.Items != nil {
in, out := &in.Items, &out.Items in, out := &in.Items, &out.Items
*out = make([]Strategy, len(*in)) *out = make([]Strategy, len(*in))

View File

@@ -56,7 +56,7 @@ func (in *Workspace) DeepCopyObject() runtime.Object {
func (in *WorkspaceList) DeepCopyInto(out *WorkspaceList) { func (in *WorkspaceList) DeepCopyInto(out *WorkspaceList) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil { if in.Items != nil {
in, out := &in.Items, &out.Items in, out := &in.Items, &out.Items
*out = make([]Workspace, len(*in)) *out = make([]Workspace, len(*in))

View File

@@ -0,0 +1,81 @@
package apiserver
import (
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/informers"
resourcev1alpha3 "kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha3"
"kubesphere.io/kubesphere/pkg/server/options"
"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/logging"
"kubesphere.io/kubesphere/pkg/simple/client/monitoring"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/simple/client/s3"
)
const (
// ApiRootPath defines the root path of all KubeSphere apis.
ApiRootPath = "/kapis"
// MimeMergePatchJson is the mime header used in merge request
MimeMergePatchJson = "application/merge-patch+json"
//
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.Interface
Monitoring monitoring.Interface
Logging logging.Interface
Devops devops.Interface
DB db.Interface
}
type APIServer struct {
// number of kubesphere apiserver
apiserverCount int
//
genericServerOptions *options.ServerRunOptions
// webservice container, where all webservice defines
container *restful.Container
// kubeClient is a collection of all kubernetes(include CRDs) objects clientset
kubeClient k8s.Client
// informerFactory is a collection of all kubernetes(include CRDs) objects informers,
// mainly for fast query
informerFactory informers.InformerFactory
// cache is used for short lived objects, like session
cache cache.Interface
//
}
func New(deps *Dependencies) *APIServer {
server := &APIServer{}
return server
}
func (s *APIServer) InstallKubeSphereAPIs() {
resourcev1alpha3.AddWebService(s.container, s.kubeClient)
}
func (s *APIServer) Serve() error {
panic("implement me")
}

View File

@@ -1,64 +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 components
import (
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/models/components"
"kubesphere.io/kubesphere/pkg/server/errors"
"net/http"
)
func GetSystemHealthStatus(request *restful.Request, response *restful.Response) {
result, err := components.GetSystemHealthStatus()
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(result)
}
// get a specific component status
func GetComponentStatus(request *restful.Request, response *restful.Response) {
component := request.PathParameter("component")
result, err := components.GetComponentStatus(component)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(result)
}
// get all componentsHandler
func GetComponents(request *restful.Request, response *restful.Response) {
result, err := components.GetAllComponentsStatus()
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(result)
}

View File

@@ -1,30 +0,0 @@
package git
import (
"net/http"
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/models/git"
"kubesphere.io/kubesphere/pkg/server/errors"
)
func GitReadVerify(request *restful.Request, response *restful.Response) {
authInfo := git.AuthInfo{}
err := request.ReadEntity(&authInfo)
ns := request.PathParameter("namespace")
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
err = git.GitReadVerify(ns, authInfo)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(errors.None)
}

View File

@@ -28,7 +28,6 @@ import (
"kubesphere.io/kubesphere/pkg/models/log" "kubesphere.io/kubesphere/pkg/models/log"
"kubesphere.io/kubesphere/pkg/server/errors" "kubesphere.io/kubesphere/pkg/server/errors"
cs "kubesphere.io/kubesphere/pkg/simple/client" cs "kubesphere.io/kubesphere/pkg/simple/client"
fb "kubesphere.io/kubesphere/pkg/simple/client/fluentbit"
"kubesphere.io/kubesphere/pkg/utils/stringutils" "kubesphere.io/kubesphere/pkg/utils/stringutils"
"net/http" "net/http"
"strconv" "strconv"

View File

@@ -28,7 +28,7 @@ import (
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/openpitrix" "kubesphere.io/kubesphere/pkg/models/openpitrix"
"kubesphere.io/kubesphere/pkg/models/resources" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/errors" "kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client" "kubesphere.io/kubesphere/pkg/simple/client"
@@ -53,7 +53,7 @@ func ListApplications(req *restful.Request, resp *restful.Response) {
} }
if namespaceName != "" { if namespaceName != "" {
namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) namespace, err := v1alpha2.GetResource("", v1alpha2.Namespaces, namespaceName)
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
@@ -109,7 +109,7 @@ func DescribeApplication(req *restful.Request, resp *restful.Response) {
return return
} }
namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) namespace, err := resources.GetResource("", v1alpha2.Namespaces, namespaceName)
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
@@ -186,7 +186,7 @@ func ModifyApplication(req *restful.Request, resp *restful.Response) {
return return
} }
namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) namespace, err := resources.GetResource("", v1alpha2.Namespaces, namespaceName)
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
@@ -243,7 +243,7 @@ func DeleteApplication(req *restful.Request, resp *restful.Response) {
return return
} }
namespace, err := resources.GetResource("", resources.Namespaces, namespaceName) namespace, err := resources.GetResource("", v1alpha2.Namespaces, namespaceName)
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)

View File

@@ -1,57 +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 operations
import (
k8serr "k8s.io/apimachinery/pkg/api/errors"
"kubesphere.io/kubesphere/pkg/models/workloads"
"kubesphere.io/kubesphere/pkg/server/errors"
"net/http"
"github.com/emicklei/go-restful"
"fmt"
)
func RerunJob(req *restful.Request, resp *restful.Response) {
var err error
job := req.PathParameter("job")
namespace := req.PathParameter("namespace")
action := req.QueryParameter("action")
resourceVersion := req.QueryParameter("resourceVersion")
switch action {
case "rerun":
err = workloads.JobReRun(namespace, job, resourceVersion)
default:
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("invalid operation %s", action)))
return
}
if err != nil {
if k8serr.IsConflict(err) {
resp.WriteHeaderAndEntity(http.StatusConflict, errors.Wrap(err))
return
}
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(errors.None)
}

View File

@@ -1,41 +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 operations
import (
"github.com/emicklei/go-restful"
"net/http"
"kubesphere.io/kubesphere/pkg/models/nodes"
"kubesphere.io/kubesphere/pkg/server/errors"
)
func DrainNode(request *restful.Request, response *restful.Response) {
nodeName := request.PathParameter("node")
err := nodes.DrainNode(nodeName)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(errors.None)
}

View File

@@ -0,0 +1,30 @@
package query
type Field string
const (
FieldName = "name"
FieldCreationTimeStamp = "creationTimestamp"
FieldLastUpdateTimestamp = "lastUpdateTimestamp"
FieldNamespace = "namespace"
FieldStatus = "status"
FieldApplication = "application"
FieldOwner = "owner"
FieldOwnerKind = "ownerKind"
)
var SortableFields = []Field{
FieldCreationTimeStamp,
FieldLastUpdateTimestamp,
FieldName,
}
// Field contains all the query field that can be compared
var ComparableFields = []Field{
FieldName,
FieldNamespace,
FieldStatus,
FieldApplication,
FieldOwner,
FieldOwnerKind,
}

View File

@@ -0,0 +1,145 @@
package query
import (
"github.com/emicklei/go-restful"
"strconv"
"strings"
)
const (
ParameterName = "name"
ParameterLabelSelector = "labelSelector"
ParameterFieldSelector = "fieldSelector"
ParameterPage = "page"
ParameterLimit = "limit"
ParameterOrderBy = "sortBy"
ParameterAscending = "ascending"
)
type Comparable interface {
Compare(Comparable) int
Contains(Comparable) bool
}
type ComparableString string
func (c ComparableString) Compare(comparable Comparable) int {
other := comparable.(ComparableString)
return strings.Compare(string(c), string(other))
}
func (c ComparableString) Contains(comparable Comparable) bool {
other := comparable.(ComparableString)
return strings.Contains(string(c), string(other))
}
// Query represents api search terms
type Query struct {
Pagination *Pagination
// sort result in which field, default to FieldCreationTimeStamp
SortBy Field
// sort result in ascending or descending order, default to descending
Ascending bool
//
Filters []Filter
}
type Pagination struct {
// items per page
Limit int
// page number
Page int
}
var NoPagination = newPagination(-1, -1)
func newPagination(limit int, page int) *Pagination {
return &Pagination{
Limit: limit,
Page: page,
}
}
func (p *Pagination) IsValidPagintaion() bool {
return p.Limit >= 0 && p.Page >= 0
}
func (p *Pagination) IsPageAvailable(total, startIndex int) bool {
return total > startIndex && p.Limit > 0
}
func (p *Pagination) GetPaginationSettings(total int) (startIndex, endIndex int) {
startIndex = p.Limit * p.Page
endIndex = startIndex + p.Limit
if endIndex > total {
endIndex = total
}
return startIndex, endIndex
}
func New() *Query {
return &Query{
Pagination: &Pagination{
Limit: -1,
Page: -1,
},
SortBy: "",
Ascending: false,
Filters: []Filter{},
}
}
type Filter struct {
Field Field
Value Comparable
}
func ParseQueryParameter(request *restful.Request) *Query {
query := New()
limit, err := strconv.ParseInt(request.QueryParameter("limit"), 10, 0)
if err != nil {
query.Pagination = NoPagination
}
page, err := strconv.ParseInt(request.QueryParameter("page"), 10, 0)
if err == nil {
query.Pagination = newPagination(int(limit), int(page-1))
}
query.SortBy = Field(defaultString(request.QueryParameter("sortBy"), FieldCreationTimeStamp))
ascending, err := strconv.ParseBool(defaultString(request.QueryParameter("ascending"), "false"))
if err != nil {
query.Ascending = false
} else {
query.Ascending = ascending
}
for _, field := range ComparableFields {
f := request.QueryParameter(string(field))
if len(f) != 0 {
query.Filters = append(query.Filters, Filter{
Field: field,
Value: ComparableString(f),
})
}
}
return query
}
func defaultString(value, defaultValue string) string {
if len(value) == 0 {
return defaultValue
}
return value
}

View File

@@ -0,0 +1,72 @@
package query
import (
"fmt"
"github.com/emicklei/go-restful"
"github.com/google/go-cmp/cmp"
"net/http"
"testing"
)
func TestParseQueryParameter(t *testing.T) {
tests := []struct {
description string
queryString string
expected *Query
}{
{
"test normal case",
"name=foo&status=Running&application=book&page=1&limit=10&ascending=true",
&Query{
Pagination: newPagination(10, 0),
SortBy: FieldCreationTimeStamp,
Ascending: true,
Filters: []Filter{
{
FieldName,
ComparableString("foo"),
},
{
FieldStatus,
ComparableString("Running"),
},
{
FieldApplication,
ComparableString("book"),
},
},
},
},
{
"test bad case",
"xxxx=xxxx&dsfsw=xxxx&page=abc&limit=add&ascending=ssss",
&Query{
Pagination: &Pagination{
Limit: -1,
Page: -1,
},
SortBy: FieldCreationTimeStamp,
Ascending: false,
Filters: []Filter{},
},
},
}
for _, test := range tests {
req, err := http.NewRequest("GET", fmt.Sprintf("http://localhost?%s", test.queryString), nil)
if err != nil {
t.Fatal(err)
}
request := restful.NewRequest(req)
t.Run(test.description, func(t *testing.T) {
got := ParseQueryParameter(request)
if diff := cmp.Diff(got, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
return
}
})
}
}

View File

@@ -1,51 +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 quotas
import (
"github.com/emicklei/go-restful"
"net/http"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/models/quotas"
)
func GetNamespaceQuotas(req *restful.Request, resp *restful.Response) {
namespace := req.PathParameter("namespace")
quota, err := quotas.GetNamespaceQuotas(namespace)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(quota)
}
func GetClusterQuotas(req *restful.Request, resp *restful.Response) {
quota, err := quotas.GetClusterQuotas()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(quota)
}

View File

@@ -1,127 +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 registries
import (
"github.com/emicklei/go-restful"
"net/http"
"kubesphere.io/kubesphere/pkg/models/registries"
"kubesphere.io/kubesphere/pkg/server/errors"
k8serror "k8s.io/apimachinery/pkg/api/errors"
log "k8s.io/klog"
)
func RegistryVerify(request *restful.Request, response *restful.Response) {
authInfo := registries.AuthInfo{}
err := request.ReadEntity(&authInfo)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
err = registries.RegistryVerify(authInfo)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(errors.None)
}
func RegistryImageBlob(request *restful.Request, response *restful.Response) {
imageName := request.QueryParameter("image")
namespace := request.QueryParameter("namespace")
secretName := request.QueryParameter("secret")
// get entry
entry, err := registries.GetEntryBySecret(namespace, secretName)
if err != nil {
log.Errorf("%+v", err)
if k8serror.IsNotFound(err) {
log.Errorf("%+v", err)
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), response)
return
}
response.WriteAsJson(&registries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
return
}
// parse image
image, err := registries.ParseImage(imageName)
if err != nil {
log.Errorf("%+v", err)
errors.ParseSvcErr(restful.NewError(http.StatusBadRequest, err.Error()), response)
return
}
// Create the registry client.
r, err := registries.CreateRegistryClient(entry.Username, entry.Password, image.Domain)
if err != nil {
log.Errorf("%+v", err)
response.WriteAsJson(&registries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
return
}
digestUrl := r.GetDigestUrl(image)
// Get token.
token, err := r.Token(digestUrl)
if err != nil {
log.Errorf("%+v", err)
response.WriteAsJson(&registries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
return
}
// Get digest.
imageManifest, err := r.ImageManifest(image, token)
if err != nil {
if serviceError, ok := err.(restful.ServiceError); ok {
response.WriteAsJson(&registries.ImageDetails{Status: registries.StatusFailed, Message: serviceError.Message})
return
}
log.Errorf("%+v", err)
response.WriteAsJson(&registries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
return
}
image.Digest = imageManifest.ManifestConfig.Digest
// Get blob.
imageBlob, err := r.ImageBlob(image, token)
if err != nil {
log.Errorf("%+v", err)
response.WriteAsJson(&registries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
return
}
imageDetails := &registries.ImageDetails{
Status: registries.StatusSuccess,
ImageManifest: imageManifest,
ImageBlob: imageBlob,
ImageTag: image.Tag,
Registry: image.Domain,
}
response.WriteAsJson(imageDetails)
}

View File

@@ -1,54 +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 resources
import (
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/models/resources"
"net/http"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params"
)
func ListNamespacedResources(req *restful.Request, resp *restful.Response) {
ListResources(req, resp)
}
func ListResources(req *restful.Request, resp *restful.Response) {
namespace := req.PathParameter("namespace")
resourceName := req.PathParameter("resources")
conditions, err := params.ParseConditions(req.QueryParameter(params.ConditionsParam))
orderBy := params.GetStringValueWithDefault(req, params.OrderByParam, resources.CreateTime)
limit, offset := params.ParsePaging(req.QueryParameter(params.PagingParam))
reverse := params.ParseReverse(req)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := resources.ListResources(namespace, resourceName, conditions, orderBy, reverse, limit, offset)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(result)
}

View File

@@ -1,71 +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 resources
import (
"github.com/emicklei/go-restful"
"k8s.io/api/core/v1"
"net/http"
"kubesphere.io/kubesphere/pkg/models/storage"
"kubesphere.io/kubesphere/pkg/server/errors"
)
type pvcList struct {
Name string `json:"name"`
Items []*v1.PersistentVolumeClaim `json:"items"`
}
type podListByPvc struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Pods []*v1.Pod `json:"pods"`
}
// List all pods of a specific PVC
// Extended API URL: "GET /api/v1alpha2/namespaces/{namespace}/persistentvolumeclaims/{name}/pods"
func GetPodListByPvc(request *restful.Request, response *restful.Response) {
pvcName := request.PathParameter("pvc")
nsName := request.PathParameter("namespace")
pods, err := storage.GetPodListByPvc(pvcName, nsName)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
result := podListByPvc{Name: pvcName, Namespace: nsName, Pods: pods}
response.WriteAsJson(result)
}
// List all PersistentVolumeClaims of a specific StorageClass
// Extended API URL: "GET /api/v1alpha2/storageclasses/{storageclass}/persistentvolumeclaims"
func GetPvcListBySc(request *restful.Request, response *restful.Response) {
scName := request.PathParameter("storageclass")
claims, err := storage.GetPvcListBySc(scName)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
result := pvcList{
Name: scName, Items: claims,
}
response.WriteAsJson(result)
}

View File

@@ -1,82 +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 revisions
import (
"net/http"
"strconv"
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/models/revisions"
"kubesphere.io/kubesphere/pkg/server/errors"
)
func GetDaemonSetRevision(req *restful.Request, resp *restful.Response) {
daemonset := req.PathParameter("daemonset")
namespace := req.PathParameter("namespace")
revision, err := strconv.Atoi(req.PathParameter("revision"))
if err != nil {
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := revisions.GetDaemonSetRevision(namespace, daemonset, revision)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(result)
}
func GetDeployRevision(req *restful.Request, resp *restful.Response) {
deploy := req.PathParameter("deployment")
namespace := req.PathParameter("namespace")
revision := req.PathParameter("revision")
result, err := revisions.GetDeployRevision(namespace, deploy, revision)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(result)
}
func GetStatefulSetRevision(req *restful.Request, resp *restful.Response) {
statefulset := req.PathParameter("statefulset")
namespace := req.PathParameter("namespace")
revision, err := strconv.Atoi(req.PathParameter("revision"))
if err != nil {
resp.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := revisions.GetStatefulSetRevision(namespace, statefulset, revision)
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(result)
}

View File

@@ -1,151 +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 routers
import (
"fmt"
"github.com/emicklei/go-restful"
k8serr "k8s.io/apimachinery/pkg/api/errors"
"net/http"
"kubesphere.io/kubesphere/pkg/server/errors"
"strings"
"k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/models/routers"
)
type Router struct {
RouterType string `json:"type"`
Annotations map[string]string `json:"annotations"`
}
// Get all namespace ingress controller services
func GetAllRouters(request *restful.Request, response *restful.Response) {
routers, err := routers.GetAllRouters()
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(routers)
}
// Get ingress controller service for specified namespace
func GetRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
router, err := routers.GetRouter(namespace)
if err != nil {
if k8serr.IsNotFound(err) {
response.WriteHeaderAndEntity(http.StatusNotFound, errors.Wrap(err))
} else {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
}
return
}
response.WriteAsJson(router)
}
// Create ingress controller and related services
func CreateRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
newRouter := Router{}
err := request.ReadEntity(&newRouter)
if err != nil {
response.WriteAsJson(err)
return
}
var router *v1.Service
serviceType, annotationMap, err := parseParameter(newRouter)
if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("wrong annotations, missing key or value")))
return
}
router, err = routers.CreateRouter(namespace, serviceType, annotationMap)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(router)
}
// Delete ingress controller and services
func DeleteRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
router, err := routers.DeleteRouter(namespace)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(router)
}
func UpdateRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
newRouter := Router{}
err := request.ReadEntity(&newRouter)
if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
serviceType, annotationMap, err := parseParameter(newRouter)
router, err := routers.UpdateRouter(namespace, serviceType, annotationMap)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(router)
}
func parseParameter(router Router) (routerType v1.ServiceType, annotationMap map[string]string, err error) {
routerType = v1.ServiceTypeNodePort
if strings.Compare(strings.ToLower(router.RouterType), "loadbalancer") == 0 {
routerType = v1.ServiceTypeLoadBalancer
}
return routerType, router.Annotations, nil
}

View File

@@ -31,7 +31,7 @@ import (
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/iam" "kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/metrics" "kubesphere.io/kubesphere/pkg/models/metrics"
"kubesphere.io/kubesphere/pkg/models/resources" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/tenant" "kubesphere.io/kubesphere/pkg/models/tenant"
"kubesphere.io/kubesphere/pkg/models/workspaces" "kubesphere.io/kubesphere/pkg/models/workspaces"
"kubesphere.io/kubesphere/pkg/server/errors" "kubesphere.io/kubesphere/pkg/server/errors"
@@ -64,7 +64,7 @@ func ListWorkspaces(req *restful.Request, resp *restful.Response) {
reverse := params.ParseReverse(req) reverse := params.ParseReverse(req)
if orderBy == "" { if orderBy == "" {
orderBy = resources.CreateTime orderBy = v1alpha2.CreateTime
reverse = true reverse = true
} }

View File

@@ -1,45 +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 workloadstatuses
import (
"github.com/emicklei/go-restful"
"net/http"
"kubesphere.io/kubesphere/pkg/models/status"
"kubesphere.io/kubesphere/pkg/server/errors"
)
func GetClusterAbnormalWorkloads(req *restful.Request, resp *restful.Response) {
res, err := status.GetClusterResourceStatus()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(res)
}
func GetNamespacedAbnormalWorkloads(req *restful.Request, resp *restful.Response) {
res, err := status.GetNamespacesResourceStatus(req.PathParameter("namespace"))
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
resp.WriteAsJson(res)
}

View File

@@ -25,6 +25,7 @@ import (
rest "k8s.io/client-go/rest" rest "k8s.io/client-go/rest"
flowcontrol "k8s.io/client-go/util/flowcontrol" flowcontrol "k8s.io/client-go/util/flowcontrol"
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2"
networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1" networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1"
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/tenant/v1alpha1" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/tenant/v1alpha1"
@@ -33,6 +34,7 @@ import (
type Interface interface { type Interface interface {
Discovery() discovery.DiscoveryInterface Discovery() discovery.DiscoveryInterface
DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface
LoggingV1alpha2() loggingv1alpha2.LoggingV1alpha2Interface
NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface
ServicemeshV1alpha2() servicemeshv1alpha2.ServicemeshV1alpha2Interface ServicemeshV1alpha2() servicemeshv1alpha2.ServicemeshV1alpha2Interface
TenantV1alpha1() tenantv1alpha1.TenantV1alpha1Interface TenantV1alpha1() tenantv1alpha1.TenantV1alpha1Interface
@@ -43,6 +45,7 @@ type Interface interface {
type Clientset struct { type Clientset struct {
*discovery.DiscoveryClient *discovery.DiscoveryClient
devopsV1alpha1 *devopsv1alpha1.DevopsV1alpha1Client devopsV1alpha1 *devopsv1alpha1.DevopsV1alpha1Client
loggingV1alpha2 *loggingv1alpha2.LoggingV1alpha2Client
networkV1alpha1 *networkv1alpha1.NetworkV1alpha1Client networkV1alpha1 *networkv1alpha1.NetworkV1alpha1Client
servicemeshV1alpha2 *servicemeshv1alpha2.ServicemeshV1alpha2Client servicemeshV1alpha2 *servicemeshv1alpha2.ServicemeshV1alpha2Client
tenantV1alpha1 *tenantv1alpha1.TenantV1alpha1Client tenantV1alpha1 *tenantv1alpha1.TenantV1alpha1Client
@@ -53,6 +56,11 @@ func (c *Clientset) DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface {
return c.devopsV1alpha1 return c.devopsV1alpha1
} }
// LoggingV1alpha2 retrieves the LoggingV1alpha2Client
func (c *Clientset) LoggingV1alpha2() loggingv1alpha2.LoggingV1alpha2Interface {
return c.loggingV1alpha2
}
// NetworkV1alpha1 retrieves the NetworkV1alpha1Client // NetworkV1alpha1 retrieves the NetworkV1alpha1Client
func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface { func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface {
return c.networkV1alpha1 return c.networkV1alpha1
@@ -93,6 +101,10 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
cs.loggingV1alpha2, err = loggingv1alpha2.NewForConfig(&configShallowCopy)
if err != nil {
return nil, err
}
cs.networkV1alpha1, err = networkv1alpha1.NewForConfig(&configShallowCopy) cs.networkV1alpha1, err = networkv1alpha1.NewForConfig(&configShallowCopy)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -118,6 +130,7 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
func NewForConfigOrDie(c *rest.Config) *Clientset { func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset var cs Clientset
cs.devopsV1alpha1 = devopsv1alpha1.NewForConfigOrDie(c) cs.devopsV1alpha1 = devopsv1alpha1.NewForConfigOrDie(c)
cs.loggingV1alpha2 = loggingv1alpha2.NewForConfigOrDie(c)
cs.networkV1alpha1 = networkv1alpha1.NewForConfigOrDie(c) cs.networkV1alpha1 = networkv1alpha1.NewForConfigOrDie(c)
cs.servicemeshV1alpha2 = servicemeshv1alpha2.NewForConfigOrDie(c) cs.servicemeshV1alpha2 = servicemeshv1alpha2.NewForConfigOrDie(c)
cs.tenantV1alpha1 = tenantv1alpha1.NewForConfigOrDie(c) cs.tenantV1alpha1 = tenantv1alpha1.NewForConfigOrDie(c)
@@ -130,6 +143,7 @@ func NewForConfigOrDie(c *rest.Config) *Clientset {
func New(c rest.Interface) *Clientset { func New(c rest.Interface) *Clientset {
var cs Clientset var cs Clientset
cs.devopsV1alpha1 = devopsv1alpha1.New(c) cs.devopsV1alpha1 = devopsv1alpha1.New(c)
cs.loggingV1alpha2 = loggingv1alpha2.New(c)
cs.networkV1alpha1 = networkv1alpha1.New(c) cs.networkV1alpha1 = networkv1alpha1.New(c)
cs.servicemeshV1alpha2 = servicemeshv1alpha2.New(c) cs.servicemeshV1alpha2 = servicemeshv1alpha2.New(c)
cs.tenantV1alpha1 = tenantv1alpha1.New(c) cs.tenantV1alpha1 = tenantv1alpha1.New(c)

View File

@@ -27,6 +27,8 @@ import (
clientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned" clientset "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1"
fakedevopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1/fake" fakedevopsv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/devops/v1alpha1/fake"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2"
fakeloggingv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2/fake"
networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1" networkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1"
fakenetworkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1/fake" fakenetworkv1alpha1 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/network/v1alpha1/fake"
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/servicemesh/v1alpha2"
@@ -87,6 +89,11 @@ func (c *Clientset) DevopsV1alpha1() devopsv1alpha1.DevopsV1alpha1Interface {
return &fakedevopsv1alpha1.FakeDevopsV1alpha1{Fake: &c.Fake} return &fakedevopsv1alpha1.FakeDevopsV1alpha1{Fake: &c.Fake}
} }
// LoggingV1alpha2 retrieves the LoggingV1alpha2Client
func (c *Clientset) LoggingV1alpha2() loggingv1alpha2.LoggingV1alpha2Interface {
return &fakeloggingv1alpha2.FakeLoggingV1alpha2{Fake: &c.Fake}
}
// NetworkV1alpha1 retrieves the NetworkV1alpha1Client // NetworkV1alpha1 retrieves the NetworkV1alpha1Client
func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface { func (c *Clientset) NetworkV1alpha1() networkv1alpha1.NetworkV1alpha1Interface {
return &fakenetworkv1alpha1.FakeNetworkV1alpha1{Fake: &c.Fake} return &fakenetworkv1alpha1.FakeNetworkV1alpha1{Fake: &c.Fake}

View File

@@ -25,6 +25,7 @@ import (
serializer "k8s.io/apimachinery/pkg/runtime/serializer" serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
@@ -35,6 +36,7 @@ var codecs = serializer.NewCodecFactory(scheme)
var parameterCodec = runtime.NewParameterCodec(scheme) var parameterCodec = runtime.NewParameterCodec(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{ var localSchemeBuilder = runtime.SchemeBuilder{
devopsv1alpha1.AddToScheme, devopsv1alpha1.AddToScheme,
loggingv1alpha2.AddToScheme,
networkv1alpha1.AddToScheme, networkv1alpha1.AddToScheme,
servicemeshv1alpha2.AddToScheme, servicemeshv1alpha2.AddToScheme,
tenantv1alpha1.AddToScheme, tenantv1alpha1.AddToScheme,

View File

@@ -25,6 +25,7 @@ import (
serializer "k8s.io/apimachinery/pkg/runtime/serializer" serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" devopsv1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
@@ -35,6 +36,7 @@ var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme) var ParameterCodec = runtime.NewParameterCodec(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{ var localSchemeBuilder = runtime.SchemeBuilder{
devopsv1alpha1.AddToScheme, devopsv1alpha1.AddToScheme,
loggingv1alpha2.AddToScheme,
networkv1alpha1.AddToScheme, networkv1alpha1.AddToScheme,
servicemeshv1alpha2.AddToScheme, servicemeshv1alpha2.AddToScheme,
tenantv1alpha1.AddToScheme, tenantv1alpha1.AddToScheme,

View File

@@ -0,0 +1,20 @@
/*
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.
// This package has the automatically generated typed clients.
package v1alpha2

View File

@@ -0,0 +1,20 @@
/*
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 has the automatically generated clients.
package fake

View File

@@ -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"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
)
// FakeFluentBits implements FluentBitInterface
type FakeFluentBits struct {
Fake *FakeLoggingV1alpha2
ns string
}
var fluentbitsResource = schema.GroupVersionResource{Group: "logging.kubesphere.io", Version: "v1alpha2", Resource: "fluentbits"}
var fluentbitsKind = schema.GroupVersionKind{Group: "logging.kubesphere.io", Version: "v1alpha2", Kind: "FluentBit"}
// Get takes name of the fluentBit, and returns the corresponding fluentBit object, and an error if there is any.
func (c *FakeFluentBits) Get(name string, options v1.GetOptions) (result *v1alpha2.FluentBit, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(fluentbitsResource, c.ns, name), &v1alpha2.FluentBit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.FluentBit), err
}
// List takes label and field selectors, and returns the list of FluentBits that match those selectors.
func (c *FakeFluentBits) List(opts v1.ListOptions) (result *v1alpha2.FluentBitList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(fluentbitsResource, fluentbitsKind, c.ns, opts), &v1alpha2.FluentBitList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &v1alpha2.FluentBitList{ListMeta: obj.(*v1alpha2.FluentBitList).ListMeta}
for _, item := range obj.(*v1alpha2.FluentBitList).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 fluentBits.
func (c *FakeFluentBits) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewWatchAction(fluentbitsResource, c.ns, opts))
}
// Create takes the representation of a fluentBit and creates it. Returns the server's representation of the fluentBit, and an error, if there is any.
func (c *FakeFluentBits) Create(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(fluentbitsResource, c.ns, fluentBit), &v1alpha2.FluentBit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.FluentBit), err
}
// Update takes the representation of a fluentBit and updates it. Returns the server's representation of the fluentBit, and an error, if there is any.
func (c *FakeFluentBits) Update(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(fluentbitsResource, c.ns, fluentBit), &v1alpha2.FluentBit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.FluentBit), 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 *FakeFluentBits) UpdateStatus(fluentBit *v1alpha2.FluentBit) (*v1alpha2.FluentBit, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(fluentbitsResource, "status", c.ns, fluentBit), &v1alpha2.FluentBit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.FluentBit), err
}
// Delete takes name of the fluentBit and deletes it. Returns an error if one occurs.
func (c *FakeFluentBits) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(fluentbitsResource, c.ns, name), &v1alpha2.FluentBit{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeFluentBits) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(fluentbitsResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &v1alpha2.FluentBitList{})
return err
}
// Patch applies the patch and returns the patched fluentBit.
func (c *FakeFluentBits) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.FluentBit, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(fluentbitsResource, c.ns, name, pt, data, subresources...), &v1alpha2.FluentBit{})
if obj == nil {
return nil, err
}
return obj.(*v1alpha2.FluentBit), err
}

View File

@@ -0,0 +1,40 @@
/*
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 (
rest "k8s.io/client-go/rest"
testing "k8s.io/client-go/testing"
v1alpha2 "kubesphere.io/kubesphere/pkg/client/clientset/versioned/typed/logging/v1alpha2"
)
type FakeLoggingV1alpha2 struct {
*testing.Fake
}
func (c *FakeLoggingV1alpha2) FluentBits(namespace string) v1alpha2.FluentBitInterface {
return &FakeFluentBits{c, namespace}
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *FakeLoggingV1alpha2) RESTClient() rest.Interface {
var ret *rest.RESTClient
return ret
}

View File

@@ -0,0 +1,191 @@
/*
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 v1alpha2
import (
"time"
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"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
scheme "kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
)
// FluentBitsGetter has a method to return a FluentBitInterface.
// A group's client should implement this interface.
type FluentBitsGetter interface {
FluentBits(namespace string) FluentBitInterface
}
// FluentBitInterface has methods to work with FluentBit resources.
type FluentBitInterface interface {
Create(*v1alpha2.FluentBit) (*v1alpha2.FluentBit, error)
Update(*v1alpha2.FluentBit) (*v1alpha2.FluentBit, error)
UpdateStatus(*v1alpha2.FluentBit) (*v1alpha2.FluentBit, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*v1alpha2.FluentBit, error)
List(opts v1.ListOptions) (*v1alpha2.FluentBitList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.FluentBit, err error)
FluentBitExpansion
}
// fluentBits implements FluentBitInterface
type fluentBits struct {
client rest.Interface
ns string
}
// newFluentBits returns a FluentBits
func newFluentBits(c *LoggingV1alpha2Client, namespace string) *fluentBits {
return &fluentBits{
client: c.RESTClient(),
ns: namespace,
}
}
// Get takes name of the fluentBit, and returns the corresponding fluentBit object, and an error if there is any.
func (c *fluentBits) Get(name string, options v1.GetOptions) (result *v1alpha2.FluentBit, err error) {
result = &v1alpha2.FluentBit{}
err = c.client.Get().
Namespace(c.ns).
Resource("fluentbits").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of FluentBits that match those selectors.
func (c *fluentBits) List(opts v1.ListOptions) (result *v1alpha2.FluentBitList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1alpha2.FluentBitList{}
err = c.client.Get().
Namespace(c.ns).
Resource("fluentbits").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested fluentBits.
func (c *fluentBits) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("fluentbits").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a fluentBit and creates it. Returns the server's representation of the fluentBit, and an error, if there is any.
func (c *fluentBits) Create(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) {
result = &v1alpha2.FluentBit{}
err = c.client.Post().
Namespace(c.ns).
Resource("fluentbits").
Body(fluentBit).
Do().
Into(result)
return
}
// Update takes the representation of a fluentBit and updates it. Returns the server's representation of the fluentBit, and an error, if there is any.
func (c *fluentBits) Update(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) {
result = &v1alpha2.FluentBit{}
err = c.client.Put().
Namespace(c.ns).
Resource("fluentbits").
Name(fluentBit.Name).
Body(fluentBit).
Do().
Into(result)
return
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *fluentBits) UpdateStatus(fluentBit *v1alpha2.FluentBit) (result *v1alpha2.FluentBit, err error) {
result = &v1alpha2.FluentBit{}
err = c.client.Put().
Namespace(c.ns).
Resource("fluentbits").
Name(fluentBit.Name).
SubResource("status").
Body(fluentBit).
Do().
Into(result)
return
}
// Delete takes name of the fluentBit and deletes it. Returns an error if one occurs.
func (c *fluentBits) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("fluentbits").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *fluentBits) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("fluentbits").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched fluentBit.
func (c *fluentBits) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha2.FluentBit, err error) {
result = &v1alpha2.FluentBit{}
err = c.client.Patch(pt).
Namespace(c.ns).
Resource("fluentbits").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}

View File

@@ -0,0 +1,21 @@
/*
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 v1alpha2
type FluentBitExpansion interface{}

View File

@@ -0,0 +1,89 @@
/*
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 v1alpha2
import (
rest "k8s.io/client-go/rest"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned/scheme"
)
type LoggingV1alpha2Interface interface {
RESTClient() rest.Interface
FluentBitsGetter
}
// LoggingV1alpha2Client is used to interact with features provided by the logging.kubesphere.io group.
type LoggingV1alpha2Client struct {
restClient rest.Interface
}
func (c *LoggingV1alpha2Client) FluentBits(namespace string) FluentBitInterface {
return newFluentBits(c, namespace)
}
// NewForConfig creates a new LoggingV1alpha2Client for the given config.
func NewForConfig(c *rest.Config) (*LoggingV1alpha2Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
if err != nil {
return nil, err
}
return &LoggingV1alpha2Client{client}, nil
}
// NewForConfigOrDie creates a new LoggingV1alpha2Client for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *LoggingV1alpha2Client {
client, err := NewForConfig(c)
if err != nil {
panic(err)
}
return client
}
// New creates a new LoggingV1alpha2Client for the given RESTClient.
func New(c rest.Interface) *LoggingV1alpha2Client {
return &LoggingV1alpha2Client{c}
}
func setConfigDefaults(config *rest.Config) error {
gv := v1alpha2.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()
}
return nil
}
// RESTClient returns a RESTClient that is used to communicate
// with API server by this client implementation.
func (c *LoggingV1alpha2Client) RESTClient() rest.Interface {
if c == nil {
return nil
}
return c.restClient
}

View File

@@ -30,6 +30,7 @@ import (
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned" versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
devops "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops" devops "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops"
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces" internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
logging "kubesphere.io/kubesphere/pkg/client/informers/externalversions/logging"
network "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network" network "kubesphere.io/kubesphere/pkg/client/informers/externalversions/network"
servicemesh "kubesphere.io/kubesphere/pkg/client/informers/externalversions/servicemesh" servicemesh "kubesphere.io/kubesphere/pkg/client/informers/externalversions/servicemesh"
tenant "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant" tenant "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant"
@@ -176,6 +177,7 @@ type SharedInformerFactory interface {
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
Devops() devops.Interface Devops() devops.Interface
Logging() logging.Interface
Network() network.Interface Network() network.Interface
Servicemesh() servicemesh.Interface Servicemesh() servicemesh.Interface
Tenant() tenant.Interface Tenant() tenant.Interface
@@ -185,6 +187,10 @@ func (f *sharedInformerFactory) Devops() devops.Interface {
return devops.New(f, f.namespace, f.tweakListOptions) return devops.New(f, f.namespace, f.tweakListOptions)
} }
func (f *sharedInformerFactory) Logging() logging.Interface {
return logging.New(f, f.namespace, f.tweakListOptions)
}
func (f *sharedInformerFactory) Network() network.Interface { func (f *sharedInformerFactory) Network() network.Interface {
return network.New(f, f.namespace, f.tweakListOptions) return network.New(f, f.namespace, f.tweakListOptions)
} }

View File

@@ -24,8 +24,9 @@ import (
schema "k8s.io/apimachinery/pkg/runtime/schema" schema "k8s.io/apimachinery/pkg/runtime/schema"
cache "k8s.io/client-go/tools/cache" cache "k8s.io/client-go/tools/cache"
v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" v1alpha1 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1" networkv1alpha1 "kubesphere.io/kubesphere/pkg/apis/network/v1alpha1"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/apis/servicemesh/v1alpha2"
tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" tenantv1alpha1 "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
) )
@@ -59,6 +60,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
case v1alpha1.SchemeGroupVersion.WithResource("s2ibinaries"): case v1alpha1.SchemeGroupVersion.WithResource("s2ibinaries"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iBinaries().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Devops().V1alpha1().S2iBinaries().Informer()}, nil
// Group=logging.kubesphere.io, Version=v1alpha2
case v1alpha2.SchemeGroupVersion.WithResource("fluentbits"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Logging().V1alpha2().FluentBits().Informer()}, nil
// Group=network.kubesphere.io, Version=v1alpha1 // Group=network.kubesphere.io, Version=v1alpha1
case networkv1alpha1.SchemeGroupVersion.WithResource("namespacenetworkpolicies"): case networkv1alpha1.SchemeGroupVersion.WithResource("namespacenetworkpolicies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().NamespaceNetworkPolicies().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().NamespaceNetworkPolicies().Informer()}, nil
@@ -66,9 +71,9 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().WorkspaceNetworkPolicies().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Network().V1alpha1().WorkspaceNetworkPolicies().Informer()}, nil
// Group=servicemesh.kubesphere.io, Version=v1alpha2 // Group=servicemesh.kubesphere.io, Version=v1alpha2
case v1alpha2.SchemeGroupVersion.WithResource("servicepolicies"): case servicemeshv1alpha2.SchemeGroupVersion.WithResource("servicepolicies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().ServicePolicies().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().ServicePolicies().Informer()}, nil
case v1alpha2.SchemeGroupVersion.WithResource("strategies"): case servicemeshv1alpha2.SchemeGroupVersion.WithResource("strategies"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().Strategies().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Servicemesh().V1alpha2().Strategies().Informer()}, nil
// Group=tenant.kubesphere.io, Version=v1alpha1 // Group=tenant.kubesphere.io, Version=v1alpha1

View File

@@ -0,0 +1,46 @@
/*
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 informer-gen. DO NOT EDIT.
package logging
import (
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
v1alpha2 "kubesphere.io/kubesphere/pkg/client/informers/externalversions/logging/v1alpha2"
)
// Interface provides access to each of this group's versions.
type Interface interface {
// V1alpha2 provides access to shared informers for resources in V1alpha2.
V1alpha2() v1alpha2.Interface
}
type group struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// V1alpha2 returns a new v1alpha2.Interface.
func (g *group) V1alpha2() v1alpha2.Interface {
return v1alpha2.New(g.factory, g.namespace, g.tweakListOptions)
}

View File

@@ -0,0 +1,89 @@
/*
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 informer-gen. DO NOT EDIT.
package v1alpha2
import (
time "time"
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"
loggingv1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
versioned "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
v1alpha2 "kubesphere.io/kubesphere/pkg/client/listers/logging/v1alpha2"
)
// FluentBitInformer provides access to a shared informer and lister for
// FluentBits.
type FluentBitInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1alpha2.FluentBitLister
}
type fluentBitInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
namespace string
}
// NewFluentBitInformer constructs a new informer for FluentBit type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFluentBitInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredFluentBitInformer(client, namespace, resyncPeriod, indexers, nil)
}
// NewFilteredFluentBitInformer constructs a new informer for FluentBit type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredFluentBitInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.LoggingV1alpha2().FluentBits(namespace).List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.LoggingV1alpha2().FluentBits(namespace).Watch(options)
},
},
&loggingv1alpha2.FluentBit{},
resyncPeriod,
indexers,
)
}
func (f *fluentBitInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredFluentBitInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *fluentBitInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&loggingv1alpha2.FluentBit{}, f.defaultInformer)
}
func (f *fluentBitInformer) Lister() v1alpha2.FluentBitLister {
return v1alpha2.NewFluentBitLister(f.Informer().GetIndexer())
}

View File

@@ -0,0 +1,45 @@
/*
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 informer-gen. DO NOT EDIT.
package v1alpha2
import (
internalinterfaces "kubesphere.io/kubesphere/pkg/client/informers/externalversions/internalinterfaces"
)
// Interface provides access to all the informers in this group version.
type Interface interface {
// FluentBits returns a FluentBitInformer.
FluentBits() FluentBitInformer
}
type version struct {
factory internalinterfaces.SharedInformerFactory
namespace string
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// New returns a new Interface.
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
}
// FluentBits returns a FluentBitInformer.
func (v *version) FluentBits() FluentBitInformer {
return &fluentBitInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}

View File

@@ -0,0 +1,27 @@
/*
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 lister-gen. DO NOT EDIT.
package v1alpha2
// FluentBitListerExpansion allows custom methods to be added to
// FluentBitLister.
type FluentBitListerExpansion interface{}
// FluentBitNamespaceListerExpansion allows custom methods to be added to
// FluentBitNamespaceLister.
type FluentBitNamespaceListerExpansion interface{}

View File

@@ -0,0 +1,94 @@
/*
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 lister-gen. DO NOT EDIT.
package v1alpha2
import (
"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/tools/cache"
v1alpha2 "kubesphere.io/kubesphere/pkg/apis/logging/v1alpha2"
)
// FluentBitLister helps list FluentBits.
type FluentBitLister interface {
// List lists all FluentBits in the indexer.
List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error)
// FluentBits returns an object that can list and get FluentBits.
FluentBits(namespace string) FluentBitNamespaceLister
FluentBitListerExpansion
}
// fluentBitLister implements the FluentBitLister interface.
type fluentBitLister struct {
indexer cache.Indexer
}
// NewFluentBitLister returns a new FluentBitLister.
func NewFluentBitLister(indexer cache.Indexer) FluentBitLister {
return &fluentBitLister{indexer: indexer}
}
// List lists all FluentBits in the indexer.
func (s *fluentBitLister) List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error) {
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha2.FluentBit))
})
return ret, err
}
// FluentBits returns an object that can list and get FluentBits.
func (s *fluentBitLister) FluentBits(namespace string) FluentBitNamespaceLister {
return fluentBitNamespaceLister{indexer: s.indexer, namespace: namespace}
}
// FluentBitNamespaceLister helps list and get FluentBits.
type FluentBitNamespaceLister interface {
// List lists all FluentBits in the indexer for a given namespace.
List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error)
// Get retrieves the FluentBit from the indexer for a given namespace and name.
Get(name string) (*v1alpha2.FluentBit, error)
FluentBitNamespaceListerExpansion
}
// fluentBitNamespaceLister implements the FluentBitNamespaceLister
// interface.
type fluentBitNamespaceLister struct {
indexer cache.Indexer
namespace string
}
// List lists all FluentBits in the indexer for a given namespace.
func (s fluentBitNamespaceLister) List(selector labels.Selector) (ret []*v1alpha2.FluentBit, err error) {
err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
ret = append(ret, m.(*v1alpha2.FluentBit))
})
return ret, err
}
// Get retrieves the FluentBit from the indexer for a given namespace and name.
func (s fluentBitNamespaceLister) Get(name string) (*v1alpha2.FluentBit, error) {
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
if err != nil {
return nil, err
}
if !exists {
return nil, errors.NewNotFound(v1alpha2.Resource("fluentbit"), name)
}
return obj.(*v1alpha2.FluentBit), nil
}

View File

@@ -31,8 +31,6 @@ const (
PorterNamespace = "porter-system" PorterNamespace = "porter-system"
IngressControllerNamespace = KubeSphereControlNamespace IngressControllerNamespace = KubeSphereControlNamespace
AdminUserName = "admin" AdminUserName = "admin"
DataHome = "/etc/kubesphere"
IngressControllerFolder = DataHome + "/ingress-controller"
IngressControllerPrefix = "kubesphere-router-" IngressControllerPrefix = "kubesphere-router-"
WorkspaceLabelKey = "kubesphere.io/workspace" WorkspaceLabelKey = "kubesphere.io/workspace"

View File

@@ -32,7 +32,6 @@ import (
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1" "kubesphere.io/kubesphere/pkg/apis/tenant/v1alpha1"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
cs "kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
"kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
@@ -101,7 +100,8 @@ var _ reconcile.Reconciler = &ReconcileNamespace{}
// ReconcileNamespace reconciles a Namespace object // ReconcileNamespace reconciles a Namespace object
type ReconcileNamespace struct { type ReconcileNamespace struct {
client.Client client.Client
scheme *runtime.Scheme openpitrixClient *openpitrix.Client
scheme *runtime.Scheme
} }
// Reconcile reads that state of the cluster for a Namespace object and makes changes based on the state read // Reconcile reads that state of the cluster for a Namespace object and makes changes based on the state read
@@ -359,18 +359,9 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace)
return nil return nil
} }
openPitrixClient, err := cs.ClientSets().OpenPitrix()
if _, notEnabled := err.(cs.ClientSetNotEnabledError); notEnabled {
return nil
} else if err != nil {
klog.Error(fmt.Sprintf("create runtime, namespace: %s, error: %s", namespace.Name, err))
return err
}
adminKubeConfigName := fmt.Sprintf("kubeconfig-%s", constants.AdminUserName) adminKubeConfigName := fmt.Sprintf("kubeconfig-%s", constants.AdminUserName)
runtimeCredentials, err := openPitrixClient.Runtime().DescribeRuntimeCredentials(openpitrix.SystemContext(), &pb.DescribeRuntimeCredentialsRequest{SearchWord: &wrappers.StringValue{Value: adminKubeConfigName}, Limit: 1}) runtimeCredentials, err := r.openpitrixClient.Runtime().DescribeRuntimeCredentials(openpitrix.SystemContext(), &pb.DescribeRuntimeCredentialsRequest{SearchWord: &wrappers.StringValue{Value: adminKubeConfigName}, Limit: 1})
if err != nil { if err != nil {
klog.Error(fmt.Sprintf("create runtime, namespace: %s, error: %s", namespace.Name, err)) klog.Error(fmt.Sprintf("create runtime, namespace: %s, error: %s", namespace.Name, err))
@@ -391,7 +382,7 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace)
return err return err
} }
resp, err := openPitrixClient.Runtime().CreateRuntimeCredential(openpitrix.SystemContext(), &pb.CreateRuntimeCredentialRequest{ resp, err := r.openpitrixClient.Runtime().CreateRuntimeCredential(openpitrix.SystemContext(), &pb.CreateRuntimeCredentialRequest{
Name: &wrappers.StringValue{Value: adminKubeConfigName}, Name: &wrappers.StringValue{Value: adminKubeConfigName},
Provider: &wrappers.StringValue{Value: "kubernetes"}, Provider: &wrappers.StringValue{Value: "kubernetes"},
Description: &wrappers.StringValue{Value: "kubeconfig"}, Description: &wrappers.StringValue{Value: "kubeconfig"},
@@ -408,7 +399,7 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace)
} }
// TODO runtime id is invalid when recreate runtime // TODO runtime id is invalid when recreate runtime
runtimeId, err := openPitrixClient.Runtime().CreateRuntime(openpitrix.SystemContext(), &pb.CreateRuntimeRequest{ runtimeId, err := r.openpitrixClient.Runtime().CreateRuntime(openpitrix.SystemContext(), &pb.CreateRuntimeRequest{
Name: &wrappers.StringValue{Value: namespace.Name}, Name: &wrappers.StringValue{Value: namespace.Name},
RuntimeCredentialId: &wrappers.StringValue{Value: kubesphereRuntimeCredentialId}, RuntimeCredentialId: &wrappers.StringValue{Value: kubesphereRuntimeCredentialId},
Provider: &wrappers.StringValue{Value: openpitrix.KubernetesProvider}, Provider: &wrappers.StringValue{Value: openpitrix.KubernetesProvider},
@@ -429,17 +420,7 @@ func (r *ReconcileNamespace) checkAndCreateRuntime(namespace *corev1.Namespace)
func (r *ReconcileNamespace) deleteRuntime(namespace *corev1.Namespace) error { func (r *ReconcileNamespace) deleteRuntime(namespace *corev1.Namespace) error {
if runtimeId := namespace.Annotations[constants.OpenPitrixRuntimeAnnotationKey]; runtimeId != "" { if runtimeId := namespace.Annotations[constants.OpenPitrixRuntimeAnnotationKey]; runtimeId != "" {
_, err := r.openpitrixClient.Runtime().DeleteRuntimes(openpitrix.SystemContext(), &pb.DeleteRuntimesRequest{RuntimeId: []string{runtimeId}, Force: &wrappers.BoolValue{Value: true}})
openPitrixClient, err := cs.ClientSets().OpenPitrix()
if _, notEnabled := err.(cs.ClientSetNotEnabledError); notEnabled {
return nil
} else if err != nil {
klog.Errorf("delete openpitrix runtime: %s, error: %s", runtimeId, err)
return err
}
_, err = openPitrixClient.Runtime().DeleteRuntimes(openpitrix.SystemContext(), &pb.DeleteRuntimesRequest{RuntimeId: []string{runtimeId}, Force: &wrappers.BoolValue{Value: true}})
if err == nil || openpitrix.IsNotFound(err) || openpitrix.IsDeleted(err) { if err == nil || openpitrix.IsNotFound(err) || openpitrix.IsDeleted(err) {
return nil return nil

View File

@@ -2,9 +2,6 @@ package s2ibinary
import ( import (
"fmt" "fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/s3"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
@@ -16,7 +13,7 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue" "k8s.io/client-go/util/workqueue"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/simple/client" "kubesphere.io/kubesphere/pkg/simple/client/s3"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
"time" "time"
@@ -39,6 +36,8 @@ type S2iBinaryController struct {
workqueue workqueue.RateLimitingInterface workqueue workqueue.RateLimitingInterface
workerLoopPeriod time.Duration workerLoopPeriod time.Duration
s3Client s3.Interface
} }
func NewController(devopsclientset devopsclient.Interface, func NewController(devopsclientset devopsclient.Interface,
@@ -205,29 +204,12 @@ func (c *S2iBinaryController) syncHandler(key string) error {
} }
func (c *S2iBinaryController) deleteBinaryInS3(s2ibin *devopsv1alpha1.S2iBinary) error { func (c *S2iBinaryController) deleteBinaryInS3(s2ibin *devopsv1alpha1.S2iBinary) error {
s3Client, err := client.ClientSets().S3()
key := fmt.Sprintf("%s-%s", s2ibin.Namespace, s2ibin.Name)
err := c.s3Client.Delete(key)
if err != nil { if err != nil {
return err klog.Errorf("error happened while deleting %s, %v", key, err)
} }
input := &s3.DeleteObjectInput{
Bucket: s3Client.Bucket(),
Key: aws.String(fmt.Sprintf("%s-%s", s2ibin.Namespace, s2ibin.Name)),
}
_, err = s3Client.Client().DeleteObject(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case s3.ErrCodeNoSuchKey:
return nil
default:
klog.Error(err, fmt.Sprintf("failed to delete s2ibin %s/%s in s3", s2ibin.Namespace, s2ibin.Name))
return err
}
} else {
klog.Error(err, fmt.Sprintf("failed to delete s2ibin %s/%s in s3", s2ibin.Namespace, s2ibin.Name))
return err
}
}
return nil return nil
} }

View File

@@ -324,15 +324,6 @@ func (r *ReconcileWorkspace) deleteGroup(instance *tenantv1alpha1.Workspace) err
} }
func (r *ReconcileWorkspace) deleteDevOpsProjects(instance *tenantv1alpha1.Workspace) error { func (r *ReconcileWorkspace) deleteDevOpsProjects(instance *tenantv1alpha1.Workspace) error {
if _, err := cs.ClientSets().Devops(); err != nil {
// skip if devops is not enabled
if _, notEnabled := err.(cs.ClientSetNotEnabledError); notEnabled {
return nil
} else {
log.Error(err, "")
return err
}
}
var wg sync.WaitGroup var wg sync.WaitGroup
log.Info("Delete DevOps Projects") log.Info("Delete DevOps Projects")

View File

@@ -18,56 +18,67 @@
package informers package informers
import ( import (
applicationclient "github.com/kubernetes-sigs/application/pkg/client/clientset/versioned"
applicationinformers "github.com/kubernetes-sigs/application/pkg/client/informers/externalversions" 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" s2iinformers "github.com/kubesphere/s2ioperator/pkg/client/informers/externalversions"
k8sinformers "k8s.io/client-go/informers" k8sinformers "k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"kubesphere.io/kubesphere/pkg/client/clientset/versioned"
ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions" ksinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/simple/client"
"sync"
"time" "time"
) )
const defaultResync = 600 * time.Second const defaultResync = 600 * time.Second
var ( type InformerFactory interface {
k8sOnce sync.Once KubernetesSharedInformerFactory() k8sinformers.SharedInformerFactory
s2iOnce sync.Once S2iSharedInformerFactory() s2iinformers.SharedInformerFactory
ksOnce sync.Once KubeSphereSharedInformerFactory() ksinformers.SharedInformerFactory
appOnce sync.Once ApplicationSharedInformerFactory() applicationinformers.SharedInformerFactory
}
type informerFactories struct {
informerFactory k8sinformers.SharedInformerFactory informerFactory k8sinformers.SharedInformerFactory
s2iInformerFactory s2iinformers.SharedInformerFactory s2iInformerFactory s2iinformers.SharedInformerFactory
ksInformerFactory ksinformers.SharedInformerFactory ksInformerFactory ksinformers.SharedInformerFactory
appInformerFactory applicationinformers.SharedInformerFactory appInformerFactory applicationinformers.SharedInformerFactory
)
func SharedInformerFactory() k8sinformers.SharedInformerFactory {
k8sOnce.Do(func() {
k8sClient := client.ClientSets().K8s().Kubernetes()
informerFactory = k8sinformers.NewSharedInformerFactory(k8sClient, defaultResync)
})
return informerFactory
} }
func S2iSharedInformerFactory() s2iinformers.SharedInformerFactory { func NewInformerFactories(client kubernetes.Interface, ksClient versioned.Interface, s2iClient s2i.Interface, appClient applicationclient.Interface) InformerFactory {
s2iOnce.Do(func() { factory := &informerFactories{}
k8sClient := client.ClientSets().K8s().S2i()
s2iInformerFactory = s2iinformers.NewSharedInformerFactory(k8sClient, defaultResync) if client != nil {
}) factory.informerFactory = k8sinformers.NewSharedInformerFactory(client, defaultResync)
return s2iInformerFactory }
if ksClient != nil {
factory.ksInformerFactory = ksinformers.NewSharedInformerFactory(ksClient, defaultResync)
}
if s2iClient != nil {
factory.s2iInformerFactory = s2iinformers.NewSharedInformerFactory(s2iClient, defaultResync)
}
if appClient != nil {
factory.appInformerFactory = applicationinformers.NewSharedInformerFactory(appClient, defaultResync)
}
return factory
} }
func KsSharedInformerFactory() ksinformers.SharedInformerFactory { func (f *informerFactories) KubernetesSharedInformerFactory() k8sinformers.SharedInformerFactory {
ksOnce.Do(func() { return f.informerFactory
k8sClient := client.ClientSets().K8s().KubeSphere()
ksInformerFactory = ksinformers.NewSharedInformerFactory(k8sClient, defaultResync)
})
return ksInformerFactory
} }
func AppSharedInformerFactory() applicationinformers.SharedInformerFactory { func (f *informerFactories) S2iSharedInformerFactory() s2iinformers.SharedInformerFactory {
appOnce.Do(func() { return f.s2iInformerFactory
appClient := client.ClientSets().K8s().Application() }
appInformerFactory = applicationinformers.NewSharedInformerFactory(appClient, defaultResync)
}) func (f *informerFactories) KubeSphereSharedInformerFactory() ksinformers.SharedInformerFactory {
return appInformerFactory return f.ksInformerFactory
}
func (f *informerFactories) ApplicationSharedInformerFactory() applicationinformers.SharedInformerFactory {
return f.appInformerFactory
} }

View File

@@ -13,16 +13,17 @@ import (
servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2" servicemeshv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/servicemesh/metrics/v1alpha2"
tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2" tenantv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/tenant/v1alpha2"
terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2" terminalv1alpha2 "kubesphere.io/kubesphere/pkg/kapis/terminal/v1alpha2"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
) )
func InstallAPIs(container *restful.Container) { func InstallAPIs(container *restful.Container, client k8s.Client) {
urlruntime.Must(servicemeshv1alpha2.AddToContainer(container)) urlruntime.Must(servicemeshv1alpha2.AddToContainer(container))
urlruntime.Must(devopsv1alpha2.AddToContainer(container)) urlruntime.Must(devopsv1alpha2.AddToContainer(container))
urlruntime.Must(loggingv1alpha2.AddToContainer(container)) urlruntime.Must(loggingv1alpha2.AddToContainer(container))
urlruntime.Must(monitoringv1alpha2.AddToContainer(container)) urlruntime.Must(monitoringv1alpha2.AddToContainer(container))
urlruntime.Must(openpitrixv1.AddToContainer(container)) urlruntime.Must(openpitrixv1.AddToContainer(container))
urlruntime.Must(operationsv1alpha2.AddToContainer(container)) urlruntime.Must(operationsv1alpha2.AddToContainer(container, client))
urlruntime.Must(resourcesv1alpha2.AddToContainer(container)) urlruntime.Must(resourcesv1alpha2.AddToContainer(container, client))
urlruntime.Must(tenantv1alpha2.AddToContainer(container)) urlruntime.Must(tenantv1alpha2.AddToContainer(container))
urlruntime.Must(terminalv1alpha2.AddToContainer(container)) urlruntime.Must(terminalv1alpha2.AddToContainer(container))
} }

View File

@@ -26,7 +26,6 @@ import (
"kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/log" "kubesphere.io/kubesphere/pkg/models/log"
fluentbitclient "kubesphere.io/kubesphere/pkg/simple/client/fluentbit"
"net/http" "net/http"
) )

View File

@@ -0,0 +1,14 @@
package v1
import "github.com/emicklei/go-restful"
type openpitrixHandler struct {
}
func newOpenpitrixHandler() *openpitrixHandler {
return &openpitrixHandler{}
}
func (h *openpitrixHandler) handleListApplications(request *restful.Request, response *restful.Response) {
}

View File

@@ -29,5 +29,5 @@ func init() {
} }
func Install(container *restful.Container) { func Install(container *restful.Container) {
urlruntime.Must(v1alpha2.AddToContainer(container)) urlruntime.Must(v1alpha2.AddToContainer(container, nil))
} }

View File

@@ -0,0 +1,48 @@
package v1alpha2
import (
"fmt"
"github.com/emicklei/go-restful"
k8serr "k8s.io/apimachinery/pkg/api/errors"
"kubesphere.io/kubesphere/pkg/models/workloads"
"kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"net/http"
)
type operationHandler struct {
jobRunner workloads.JobRunner
}
func newOperationHandler(client k8s.Client) *operationHandler {
return &operationHandler{
jobRunner: workloads.NewJobRunner(client.Kubernetes()),
}
}
func (r *operationHandler) handleJobReRun(request *restful.Request, response *restful.Response) {
var err error
job := request.PathParameter("job")
namespace := request.PathParameter("namespace")
action := request.QueryParameter("action")
resourceVersion := request.QueryParameter("resourceVersion")
switch action {
case "rerun":
err = r.jobRunner.JobReRun(namespace, job, resourceVersion)
default:
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("invalid operation %s", action)))
return
}
if err != nil {
if k8serr.IsConflict(err) {
response.WriteHeaderAndEntity(http.StatusConflict, errors.Wrap(err))
return
}
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(errors.None)
}

View File

@@ -20,9 +20,9 @@ package v1alpha2
import ( import (
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/apiserver/operations"
"kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/server/errors" "kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"net/http" "net/http"
) )
@@ -30,25 +30,15 @@ const GroupName = "operations.kubesphere.io"
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
var ( func AddToContainer(c *restful.Container, client k8s.Client) error {
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
AddToContainer = WebServiceBuilder.AddToContainer
)
func addWebService(c *restful.Container) error {
ok := "ok" ok := "ok"
webservice := runtime.NewWebService(GroupVersion) webservice := runtime.NewWebService(GroupVersion)
webservice.Route(webservice.POST("/nodes/{node}/drainage"). handler := newOperationHandler(client)
To(operations.DrainNode).
Deprecate().
Doc("remove a node from service, safely evict all of your pods from a node and you can power down the node. More info: https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/").
Param(webservice.PathParameter("node", "node name")).
Returns(http.StatusOK, ok, errors.Error{}))
webservice.Route(webservice.POST("/namespaces/{namespace}/jobs/{job}"). webservice.Route(webservice.POST("/namespaces/{namespace}/jobs/{job}").
To(operations.RerunJob). To(handler.handleJobReRun).
Doc("Rerun job whether the job is complete or not"). Doc("Rerun job whether the job is complete or not").
Deprecate(). Deprecate().
Param(webservice.PathParameter("job", "job name")). Param(webservice.PathParameter("job", "job name")).

View File

@@ -1,33 +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 install
import (
"github.com/emicklei/go-restful"
urlruntime "k8s.io/apimachinery/pkg/util/runtime"
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/kapis/resources/v1alpha2"
)
func init() {
Install(runtime.Container)
}
func Install(c *restful.Container) {
urlruntime.Must(v1alpha2.AddToContainer(c))
}

View File

@@ -0,0 +1,345 @@
package v1alpha2
import (
"fmt"
"github.com/emicklei/go-restful"
v1 "k8s.io/api/core/v1"
k8serr "k8s.io/apimachinery/pkg/api/errors"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models/components"
"kubesphere.io/kubesphere/pkg/models/git"
"kubesphere.io/kubesphere/pkg/models/quotas"
"kubesphere.io/kubesphere/pkg/models/registries"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/models/resources/v1alpha2/resource"
"kubesphere.io/kubesphere/pkg/models/revisions"
"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"
)
type resourceHandler struct {
resourcesGetter *resource.ResourceGetter
componentsGetter components.ComponentsGetter
resourceQuotaGetter quotas.ResourceQuotaGetter
revisionGetter revisions.RevisionGetter
routerOperator routers.RouterOperator
gitVerifier git.GitVerifier
registryGetter registries.RegistryGetter
}
func newResourceHandler(client k8s.Client) *resourceHandler {
factory := informers.NewInformerFactories(client.Kubernetes(), client.KubeSphere(), client.S2i(), client.Application())
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()),
gitVerifier: git.NewGitVerifier(factory.KubernetesSharedInformerFactory()),
registryGetter: registries.NewRegistryGetter(factory.KubernetesSharedInformerFactory()),
}
}
func (r *resourceHandler) handleGetNamespacedResources(request *restful.Request, response *restful.Response) {
r.handleListNamespaceResources(request, response)
}
func (r *resourceHandler) handleListNamespaceResources(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
resourceName := request.PathParameter("resources")
conditions, err := params.ParseConditions(request.QueryParameter(params.ConditionsParam))
orderBy := params.GetStringValueWithDefault(request, params.OrderByParam, v1alpha2.CreateTime)
limit, offset := params.ParsePaging(request.QueryParameter(params.PagingParam))
reverse := params.ParseReverse(request)
if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, err)
return
}
result, err := r.resourcesGetter.ListResources(namespace, resourceName, conditions, orderBy, reverse, limit, offset)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetSystemHealthStatus(_ *restful.Request, response *restful.Response) {
result, err := r.componentsGetter.GetSystemHealthStatus()
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetComponentStatus(request *restful.Request, response *restful.Response) {
component := request.PathParameter("component")
result, err := r.componentsGetter.GetComponentStatus(component)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetComponents(_ *restful.Request, response *restful.Response) {
result, err := r.componentsGetter.GetAllComponentsStatus()
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetClusterQuotas(_ *restful.Request, response *restful.Response) {
result, err := r.resourceQuotaGetter.GetClusterQuota()
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetNamespaceQuotas(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
quota, err := r.resourceQuotaGetter.GetNamespaceQuota(namespace)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(quota)
}
func (r *resourceHandler) handleGetDaemonSetRevision(request *restful.Request, response *restful.Response) {
daemonset := request.PathParameter("daemonset")
namespace := request.PathParameter("namespace")
revision, err := strconv.Atoi(request.PathParameter("revision"))
if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := r.revisionGetter.GetDaemonSetRevision(namespace, daemonset, revision)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetDeploymentRevision(request *restful.Request, response *restful.Response) {
deploy := request.PathParameter("deployment")
namespace := request.PathParameter("namespace")
revision := request.PathParameter("revision")
result, err := r.revisionGetter.GetDeploymentRevision(namespace, deploy, revision)
if err != nil {
response.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
return
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetStatefulSetRevision(request *restful.Request, response *restful.Response) {
statefulset := request.PathParameter("statefulset")
namespace := request.PathParameter("namespace")
revision, err := strconv.Atoi(request.PathParameter("revision"))
if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
result, err := r.revisionGetter.GetStatefulSetRevision(namespace, statefulset, revision)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(result)
}
// Get ingress controller service for specified namespace
func (r *resourceHandler) handleGetRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
router, err := r.routerOperator.GetRouter(namespace)
if err != nil {
if k8serr.IsNotFound(err) {
response.WriteHeaderAndEntity(http.StatusNotFound, errors.Wrap(err))
} else {
api.HandleInternalError(response, err)
}
return
}
response.WriteAsJson(router)
}
// Create ingress controller and related services
func (r *resourceHandler) handleCreateRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
newRouter := api.Router{}
err := request.ReadEntity(&newRouter)
if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(fmt.Errorf("wrong annotations, missing key or value")))
return
}
routerType := v1.ServiceTypeNodePort
if strings.Compare(strings.ToLower(newRouter.RouterType), "loadbalancer") == 0 {
routerType = v1.ServiceTypeLoadBalancer
}
router, err := r.routerOperator.CreateRouter(namespace, routerType, newRouter.Annotations)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(router)
}
// Delete ingress controller and services
func (r *resourceHandler) handleDeleteRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
router, err := r.routerOperator.DeleteRouter(namespace)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(router)
}
func (r *resourceHandler) handleUpdateRouter(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
newRouter := api.Router{}
err := request.ReadEntity(&newRouter)
if err != nil {
response.WriteHeaderAndEntity(http.StatusBadRequest, errors.Wrap(err))
return
}
var routerType = v1.ServiceTypeNodePort
if strings.Compare(strings.ToLower(newRouter.RouterType), "loadbalancer") == 0 {
routerType = v1.ServiceTypeLoadBalancer
}
router, err := r.routerOperator.UpdateRouter(namespace, routerType, newRouter.Annotations)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteAsJson(router)
}
func (r *resourceHandler) handleVerifyGitCredential(request *restful.Request, response *restful.Response) {
var credential api.GitCredential
err := request.ReadEntity(&credential)
if err != nil {
api.HandleBadRequest(response, err)
return
}
err = r.gitVerifier.VerifyGitCredential(credential.RemoteUrl, credential.SecretRef.Namespace, credential.SecretRef.Name)
if err != nil {
api.HandleBadRequest(response, err)
return
}
response.WriteHeader(http.StatusOK)
}
func (r *resourceHandler) handleVerifyRegistryCredential(request *restful.Request, response *restful.Response) {
var credential api.RegistryCredential
err := request.ReadEntity(&credential)
if err != nil {
api.HandleBadRequest(response, err)
return
}
err = r.registryGetter.VerifyRegistryCredential(credential)
if err != nil {
api.HandleBadRequest(response, err)
return
}
response.WriteHeader(http.StatusOK)
}
func (r *resourceHandler) handleGetRegistryEntry(request *restful.Request, response *restful.Response) {
imageName := request.QueryParameter("image")
namespace := request.QueryParameter("namespace")
secretName := request.QueryParameter("secret")
detail, err := r.registryGetter.GetEntry(namespace, secretName, imageName)
if err != nil {
api.HandleBadRequest(response, err)
return
}
response.WriteAsJson(detail)
}
func (r *resourceHandler) handleGetNamespacedAbnormalWorkloads(request *restful.Request, response *restful.Response) {
namespace := request.PathParameter("namespace")
result := api.Workloads{
Namespace: namespace,
Count: make(map[string]int),
}
for _, workloadType := range []string{api.ResourceKindDeployment, api.ResourceKindStatefulSet, api.ResourceKindDaemonSet, api.ResourceKindJob, api.ResourceKindPersistentVolumeClaim} {
var notReadyStatus string
switch workloadType {
case api.ResourceKindPersistentVolumeClaim:
notReadyStatus = strings.Join([]string{v1alpha2.StatusPending, v1alpha2.StatusLost}, "|")
case api.ResourceKindJob:
notReadyStatus = v1alpha2.StatusFailed
default:
notReadyStatus = v1alpha2.StatusUpdating
}
res, err := r.resourcesGetter.ListResources(namespace, workloadType, &params.Conditions{Match: map[string]string{v1alpha2.Status: notReadyStatus}}, "", false, -1, 0)
if err != nil {
api.HandleInternalError(response, err)
}
result.Count[workloadType] = len(res.Items)
}
response.WriteAsJson(result)
}
func (r *resourceHandler) handleGetAbnormalWorkloads(request *restful.Request, response *restful.Response) {
r.handleGetNamespacedAbnormalWorkloads(request, response)
}

View File

@@ -23,43 +23,32 @@ import (
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/apiserver/components" "kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/git" "kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
"kubesphere.io/kubesphere/pkg/apiserver/operations"
"kubesphere.io/kubesphere/pkg/apiserver/quotas"
"kubesphere.io/kubesphere/pkg/apiserver/registries"
"kubesphere.io/kubesphere/pkg/apiserver/resources" "kubesphere.io/kubesphere/pkg/apiserver/resources"
"kubesphere.io/kubesphere/pkg/apiserver/revisions"
"kubesphere.io/kubesphere/pkg/apiserver/routers"
"kubesphere.io/kubesphere/pkg/apiserver/runtime" "kubesphere.io/kubesphere/pkg/apiserver/runtime"
"kubesphere.io/kubesphere/pkg/apiserver/workloadstatuses"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models"
gitmodel "kubesphere.io/kubesphere/pkg/models/git" gitmodel "kubesphere.io/kubesphere/pkg/models/git"
registriesmodel "kubesphere.io/kubesphere/pkg/models/registries" registriesmodel "kubesphere.io/kubesphere/pkg/models/registries"
"kubesphere.io/kubesphere/pkg/models/status"
"kubesphere.io/kubesphere/pkg/server/errors" "kubesphere.io/kubesphere/pkg/server/errors"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"net/http" "net/http"
) )
const GroupName = "resources.kubesphere.io" const (
GroupName = "resources.kubesphere.io"
)
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
var ( func AddToContainer(c *restful.Container, client k8s.Client) error {
WebServiceBuilder = runtime.NewContainerBuilder(addWebService)
AddToContainer = WebServiceBuilder.AddToContainer
)
func addWebService(c *restful.Container) error {
webservice := runtime.NewWebService(GroupVersion) webservice := runtime.NewWebService(GroupVersion)
handler := newResourceHandler(client)
ok := "ok"
webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}"). webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}").
To(resources.ListNamespacedResources). To(handler.handleListNamespaceResources).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Doc("Namespace level resource query"). Doc("Namespace level resource query").
Param(webservice.PathParameter("namespace", "the name of the project")). Param(webservice.PathParameter("namespace", "the name of the project")).
@@ -73,21 +62,11 @@ func addWebService(c *restful.Container) error {
DefaultValue("limit=10,page=1")). DefaultValue("limit=10,page=1")).
Param(webservice.QueryParameter(params.ReverseParam, "sort parameters, e.g. reverse=true")). Param(webservice.QueryParameter(params.ReverseParam, "sort parameters, e.g. reverse=true")).
Param(webservice.QueryParameter(params.OrderByParam, "sort parameters, e.g. orderBy=createTime")). Param(webservice.QueryParameter(params.OrderByParam, "sort parameters, e.g. orderBy=createTime")).
Returns(http.StatusOK, ok, models.PageableResponse{})) Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}))
webservice.Route(webservice.POST("/namespaces/{namespace}/jobs/{job}").
To(operations.RerunJob).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Doc("Rerun job whether the job is complete or not").
Param(webservice.PathParameter("job", "job name")).
Param(webservice.PathParameter("namespace", "the name of the namespace where the job runs in")).
Param(webservice.QueryParameter("action", "action must be \"rerun\"")).
Param(webservice.QueryParameter("resourceVersion", "version of job, rerun when the version matches")).
Returns(http.StatusOK, ok, errors.Error{}))
webservice.Route(webservice.GET("/{resources}"). webservice.Route(webservice.GET("/{resources}").
To(resources.ListResources). To(handler.handleListNamespaceResources).
Returns(http.StatusOK, ok, models.PageableResponse{}). Returns(http.StatusOK, api.StatusOK, models.PageableResponse{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}).
Doc("Cluster level resource query"). Doc("Cluster level resource query").
Param(webservice.PathParameter("resources", "cluster level resource type, e.g. nodes,workspaces,storageclasses,clusterroles.")). Param(webservice.PathParameter("resources", "cluster level resource type, e.g. nodes,workspaces,storageclasses,clusterroles.")).
@@ -102,67 +81,60 @@ func addWebService(c *restful.Container) error {
Param(webservice.QueryParameter(params.ReverseParam, "sort parameters, e.g. reverse=true")). Param(webservice.QueryParameter(params.ReverseParam, "sort parameters, e.g. reverse=true")).
Param(webservice.QueryParameter(params.OrderByParam, "sort parameters, e.g. orderBy=createTime"))) Param(webservice.QueryParameter(params.OrderByParam, "sort parameters, e.g. orderBy=createTime")))
webservice.Route(webservice.POST("/nodes/{node}/drainage").
To(operations.DrainNode).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}).
Doc("remove a node from service, safely evict all of your pods from a node and you can power down the node. More info: https://kubernetes.io/docs/tasks/administer-cluster/safely-drain-node/").
Param(webservice.PathParameter("node", "node name")).
Returns(http.StatusOK, ok, errors.Error{}))
webservice.Route(webservice.GET("/users/{user}/kubectl"). webservice.Route(webservice.GET("/users/{user}/kubectl").
To(resources.GetKubectl). To(resources.GetKubectl).
Doc("get user's kubectl pod"). Doc("get user's kubectl pod").
Param(webservice.PathParameter("user", "username")). Param(webservice.PathParameter("user", "username")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserResourcesTag}).
Returns(http.StatusOK, ok, models.PodInfo{})) Returns(http.StatusOK, api.StatusOK, models.PodInfo{}))
webservice.Route(webservice.GET("/users/{user}/kubeconfig"). webservice.Route(webservice.GET("/users/{user}/kubeconfig").
Produces("text/plain", restful.MIME_JSON). Produces("text/plain", restful.MIME_JSON).
To(resources.GetKubeconfig). To(resources.GetKubeconfig).
Doc("get users' kubeconfig"). Doc("get users' kubeconfig").
Param(webservice.PathParameter("user", "username")). Param(webservice.PathParameter("user", "username")).
Returns(http.StatusOK, ok, ""). Returns(http.StatusOK, api.StatusOK, "").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserResourcesTag})) Metadata(restfulspec.KeyOpenAPITags, []string{constants.UserResourcesTag}))
webservice.Route(webservice.GET("/components"). webservice.Route(webservice.GET("/components").
To(components.GetComponents). To(handler.handleGetComponents).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}).
Doc("List the system components."). Doc("List the system components.").
Returns(http.StatusOK, ok, []models.ComponentStatus{})) Returns(http.StatusOK, api.StatusOK, []v1alpha2.ComponentStatus{}))
webservice.Route(webservice.GET("/components/{component}"). webservice.Route(webservice.GET("/components/{component}").
To(components.GetComponentStatus). To(handler.handleGetComponentStatus).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}).
Doc("Describe the specified system component."). Doc("Describe the specified system component.").
Param(webservice.PathParameter("component", "component name")). Param(webservice.PathParameter("component", "component name")).
Returns(http.StatusOK, ok, models.ComponentStatus{})) Returns(http.StatusOK, api.StatusOK, v1alpha2.ComponentStatus{}))
webservice.Route(webservice.GET("/componenthealth"). webservice.Route(webservice.GET("/componenthealth").
To(components.GetSystemHealthStatus). To(handler.handleGetSystemHealthStatus).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ComponentStatusTag}).
Doc("Get the health status of system components."). Doc("Get the health status of system components.").
Returns(http.StatusOK, ok, models.HealthStatus{})) Returns(http.StatusOK, api.StatusOK, v1alpha2.HealthStatus{}))
webservice.Route(webservice.GET("/quotas"). webservice.Route(webservice.GET("/quotas").
To(quotas.GetClusterQuotas). To(handler.handleGetClusterQuotas).
Doc("get whole cluster's resource usage"). Doc("get whole cluster's resource usage").
Returns(http.StatusOK, ok, models.ResourceQuota{}). Returns(http.StatusOK, api.StatusOK, api.ResourceQuota{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag})) Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}))
webservice.Route(webservice.GET("/namespaces/{namespace}/quotas"). webservice.Route(webservice.GET("/namespaces/{namespace}/quotas").
Doc("get specified namespace's resource quota and usage"). Doc("get specified namespace's resource quota and usage").
Param(webservice.PathParameter("namespace", "the name of the project")). Param(webservice.PathParameter("namespace", "the name of the project")).
Returns(http.StatusOK, ok, models.ResourceQuota{}). Returns(http.StatusOK, api.StatusOK, api.ResourceQuota{}).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
To(quotas.GetNamespaceQuotas)) To(handler.handleGetNamespaceQuotas))
webservice.Route(webservice.POST("registry/verify"). webservice.Route(webservice.POST("registry/verify").
To(registries.RegistryVerify). To(handler.handleVerifyRegistryCredential).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.VerificationTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.VerificationTag}).
Doc("verify if a user has access to the docker registry"). Doc("verify if a user has access to the docker registry").
Reads(registriesmodel.AuthInfo{}). Reads(api.RegistryCredential{}).
Returns(http.StatusOK, ok, errors.Error{})) Returns(http.StatusOK, api.StatusOK, errors.Error{}))
webservice.Route(webservice.GET("/registry/blob"). webservice.Route(webservice.GET("/registry/blob").
To(registries.RegistryImageBlob). To(handler.handleGetRegistryEntry).
Param(webservice.QueryParameter("image", "query image, condition for filtering."). Param(webservice.QueryParameter("image", "query image, condition for filtering.").
Required(true). Required(true).
DataFormat("image=%s")). DataFormat("image=%s")).
@@ -175,87 +147,80 @@ func addWebService(c *restful.Container) error {
Metadata(restfulspec.KeyOpenAPITags, []string{constants.RegistryTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.RegistryTag}).
Doc("Retrieve the blob from the registry identified"). Doc("Retrieve the blob from the registry identified").
Writes(registriesmodel.ImageDetails{}). Writes(registriesmodel.ImageDetails{}).
Returns(http.StatusOK, ok, registriesmodel.ImageDetails{}), Returns(http.StatusOK, api.StatusOK, registriesmodel.ImageDetails{}),
) )
webservice.Route(webservice.POST("git/verify"). webservice.Route(webservice.POST("git/verify").
To(git.GitReadVerify). To(handler.handleVerifyGitCredential).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.VerificationTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.VerificationTag}).
Doc("Verify if the kubernetes secret has read access to the git repository"). Doc("Verify if the kubernetes secret has read access to the git repository").
Reads(gitmodel.AuthInfo{}). Reads(gitmodel.AuthInfo{}).
Returns(http.StatusOK, ok, errors.Error{}), Returns(http.StatusOK, api.StatusOK, errors.Error{}),
) )
webservice.Route(webservice.GET("/namespaces/{namespace}/daemonsets/{daemonset}/revisions/{revision}"). webservice.Route(webservice.GET("/namespaces/{namespace}/daemonsets/{daemonset}/revisions/{revision}").
To(revisions.GetDaemonSetRevision). To(handler.handleGetDaemonSetRevision).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Doc("Get the specified daemonset revision"). Doc("Get the specified daemonset revision").
Param(webservice.PathParameter("daemonset", "the name of the daemonset")). Param(webservice.PathParameter("daemonset", "the name of the daemonset")).
Param(webservice.PathParameter("namespace", "the namespace of the daemonset")). Param(webservice.PathParameter("namespace", "the namespace of the daemonset")).
Param(webservice.PathParameter("revision", "the revision of the daemonset")). Param(webservice.PathParameter("revision", "the revision of the daemonset")).
Returns(http.StatusOK, ok, appsv1.DaemonSet{})) Returns(http.StatusOK, api.StatusOK, appsv1.DaemonSet{}))
webservice.Route(webservice.GET("/namespaces/{namespace}/deployments/{deployment}/revisions/{revision}"). webservice.Route(webservice.GET("/namespaces/{namespace}/deployments/{deployment}/revisions/{revision}").
To(revisions.GetDeployRevision). To(handler.handleGetDeploymentRevision).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Doc("Get the specified deployment revision"). Doc("Get the specified deployment revision").
Param(webservice.PathParameter("deployment", "the name of deployment")). Param(webservice.PathParameter("deployment", "the name of deployment")).
Param(webservice.PathParameter("namespace", "the namespace of the deployment")). Param(webservice.PathParameter("namespace", "the namespace of the deployment")).
Param(webservice.PathParameter("revision", "the revision of the deployment")). Param(webservice.PathParameter("revision", "the revision of the deployment")).
Returns(http.StatusOK, ok, appsv1.ReplicaSet{})) Returns(http.StatusOK, api.StatusOK, appsv1.ReplicaSet{}))
webservice.Route(webservice.GET("/namespaces/{namespace}/statefulsets/{statefulset}/revisions/{revision}"). webservice.Route(webservice.GET("/namespaces/{namespace}/statefulsets/{statefulset}/revisions/{revision}").
To(revisions.GetStatefulSetRevision). To(handler.handleGetStatefulSetRevision).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Doc("Get the specified statefulset revision"). Doc("Get the specified statefulset revision").
Param(webservice.PathParameter("statefulset", "the name of the statefulset")). Param(webservice.PathParameter("statefulset", "the name of the statefulset")).
Param(webservice.PathParameter("namespace", "the namespace of the statefulset")). Param(webservice.PathParameter("namespace", "the namespace of the statefulset")).
Param(webservice.PathParameter("revision", "the revision of the statefulset")). Param(webservice.PathParameter("revision", "the revision of the statefulset")).
Returns(http.StatusOK, ok, appsv1.StatefulSet{})) Returns(http.StatusOK, api.StatusOK, appsv1.StatefulSet{}))
webservice.Route(webservice.GET("/routers").
To(routers.GetAllRouters).
Doc("List all routers of all projects").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}).
Returns(http.StatusOK, ok, corev1.ServiceList{}))
webservice.Route(webservice.GET("/namespaces/{namespace}/router"). webservice.Route(webservice.GET("/namespaces/{namespace}/router").
To(routers.GetRouter). To(handler.handleGetRouter).
Doc("List router of a specified project"). Doc("List router of a specified project").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Returns(http.StatusOK, ok, corev1.Service{}). Returns(http.StatusOK, api.StatusOK, corev1.Service{}).
Param(webservice.PathParameter("namespace", "the name of the project"))) Param(webservice.PathParameter("namespace", "the name of the project")))
webservice.Route(webservice.DELETE("/namespaces/{namespace}/router"). webservice.Route(webservice.DELETE("/namespaces/{namespace}/router").
To(routers.DeleteRouter). To(handler.handleDeleteRouter).
Doc("List router of a specified project"). Doc("List router of a specified project").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Returns(http.StatusOK, ok, corev1.Service{}). Returns(http.StatusOK, api.StatusOK, corev1.Service{}).
Param(webservice.PathParameter("namespace", "the name of the project"))) Param(webservice.PathParameter("namespace", "the name of the project")))
webservice.Route(webservice.POST("/namespaces/{namespace}/router"). webservice.Route(webservice.POST("/namespaces/{namespace}/router").
To(routers.CreateRouter). To(handler.handleCreateRouter).
Doc("Create a router for a specified project"). Doc("Create a router for a specified project").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Returns(http.StatusOK, ok, corev1.Service{}). Returns(http.StatusOK, api.StatusOK, corev1.Service{}).
Param(webservice.PathParameter("namespace", "the name of the project"))) Param(webservice.PathParameter("namespace", "the name of the project")))
webservice.Route(webservice.PUT("/namespaces/{namespace}/router"). webservice.Route(webservice.PUT("/namespaces/{namespace}/router").
To(routers.UpdateRouter). To(handler.handleUpdateRouter).
Doc("Update a router for a specified project"). Doc("Update a router for a specified project").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Returns(http.StatusOK, ok, corev1.Service{}). Returns(http.StatusOK, api.StatusOK, corev1.Service{}).
Param(webservice.PathParameter("namespace", "the name of the project"))) Param(webservice.PathParameter("namespace", "the name of the project")))
webservice.Route(webservice.GET("/abnormalworkloads"). webservice.Route(webservice.GET("/abnormalworkloads").
Doc("get abnormal workloads' count of whole cluster"). Doc("get abnormal workloads' count of whole cluster").
Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.ClusterResourcesTag}).
Returns(http.StatusOK, ok, status.WorkLoadStatus{}). Returns(http.StatusOK, api.StatusOK, api.Workloads{}).
To(workloadstatuses.GetClusterAbnormalWorkloads)) To(handler.handleGetAbnormalWorkloads))
webservice.Route(webservice.GET("/namespaces/{namespace}/abnormalworkloads"). webservice.Route(webservice.GET("/namespaces/{namespace}/abnormalworkloads").
Doc("get abnormal workloads' count of specified namespace"). Doc("get abnormal workloads' count of specified namespace").
Param(webservice.PathParameter("namespace", "the name of the project")). Param(webservice.PathParameter("namespace", "the name of the project")).
Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}). Metadata(restfulspec.KeyOpenAPITags, []string{constants.NamespaceResourcesTag}).
Returns(http.StatusOK, ok, status.WorkLoadStatus{}). Returns(http.StatusOK, api.StatusOK, api.Workloads{}).
To(workloadstatuses.GetNamespacedAbnormalWorkloads)) To(handler.handleGetNamespacedAbnormalWorkloads))
c.Add(webservice) c.Add(webservice)

View File

@@ -0,0 +1,91 @@
package v1alpha3
import (
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/apiserver/query"
"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"
)
type Handler struct {
namespacedResourceGetter *resource.NamespacedResourceGetter
componentsGetter components.ComponentsGetter
}
func New(client k8s.Client) *Handler {
factory := informers.NewInformerFactories(client.Kubernetes(), nil, nil, nil)
return &Handler{
namespacedResourceGetter: resource.New(factory.KubernetesSharedInformerFactory()),
componentsGetter: components.NewComponentsGetter(factory.KubernetesSharedInformerFactory()),
}
}
func (h Handler) handleGetNamespacedResource(request *restful.Request, response *restful.Response) {
resource := request.PathParameter("resources")
namespace := request.PathParameter("namespace")
name := request.PathParameter("name")
result, err := h.namespacedResourceGetter.Get(resource, namespace, name)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusOK, result)
}
// handleListNamedResource retrieves namespaced scope resources
func (h Handler) handleListNamespacedResource(request *restful.Request, response *restful.Response) {
query := query.ParseQueryParameter(request)
resource := request.PathParameter("resources")
namespace := request.PathParameter("namespace")
result, err := h.namespacedResourceGetter.List(resource, namespace, query)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusOK, result)
}
func (h Handler) handleGetComponentStatus(request *restful.Request, response *restful.Response) {
component := request.PathParameter("component")
result, err := h.componentsGetter.GetComponentStatus(component)
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusOK, result)
}
func (h Handler) handleGetSystemHealthStatus(request *restful.Request, response *restful.Response) {
result, err := h.componentsGetter.GetSystemHealthStatus()
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusOK, result)
}
// get all componentsHandler
func (h Handler) handleGetComponents(request *restful.Request, response *restful.Response) {
result, err := h.componentsGetter.GetAllComponentsStatus()
if err != nil {
api.HandleInternalError(response, err)
return
}
response.WriteHeaderAndEntity(http.StatusOK, result)
}

View File

@@ -0,0 +1,7 @@
package v1alpha3
import "testing"
func TestComponentHandler(t *testing.T) {
}

View File

@@ -0,0 +1,81 @@
/*
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 v1alpha3
import (
"github.com/emicklei/go-restful"
"github.com/emicklei/go-restful-openapi"
"k8s.io/apimachinery/pkg/runtime/schema"
"kubesphere.io/kubesphere/pkg/api"
"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"
"net/http"
)
const (
GroupName = "resources.kubesphere.io"
tagComponentStatus = "Component Status"
tagNamespacedResource = "Namespaced Resource"
ok = "OK"
)
var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"}
func AddWebService(c *restful.Container, client k8s.Client) error {
webservice := runtime.NewWebService(GroupVersion)
handler := New(client)
webservice.Route(webservice.GET("/namespaces/{namespace}/{resources}").
To(handler.handleGetNamespacedResource).
Metadata(restfulspec.KeyOpenAPITags, []string{tagNamespacedResource}).
Doc("Namespace level resource query").
Param(webservice.PathParameter("namespace", "the name of the project")).
Param(webservice.PathParameter("resources", "namespace level resource type, e.g. pods,jobs,configmaps,services.")).
Param(webservice.QueryParameter(query.ParameterName, "name used to do filtering").Required(false)).
Param(webservice.QueryParameter(query.ParameterPage, "page").Required(false).DataFormat("page=%d").DefaultValue("page=0")).
Param(webservice.QueryParameter(query.ParameterLimit, "limit").Required(false)).
Param(webservice.QueryParameter(query.ParameterAscending, "sort parameters, e.g. reverse=true").Required(false).DefaultValue("ascending=false")).
Param(webservice.QueryParameter(query.ParameterOrderBy, "sort parameters, e.g. orderBy=createTime")).
Returns(http.StatusOK, ok, api.ListResult{}))
webservice.Route(webservice.GET("/components").
To(handler.handleGetComponents).
Metadata(restfulspec.KeyOpenAPITags, []string{tagComponentStatus}).
Doc("List the system components.").
Returns(http.StatusOK, ok, []v1alpha2.ComponentStatus{}))
webservice.Route(webservice.GET("/components/{component}").
To(handler.handleGetComponentStatus).
Metadata(restfulspec.KeyOpenAPITags, []string{tagComponentStatus}).
Doc("Describe the specified system component.").
Param(webservice.PathParameter("component", "component name")).
Returns(http.StatusOK, ok, v1alpha2.ComponentStatus{}))
webservice.Route(webservice.GET("/componenthealth").
To(handler.handleGetSystemHealthStatus).
Metadata(restfulspec.KeyOpenAPITags, []string{tagComponentStatus}).
Doc("Get the health status of system components.").
Returns(http.StatusOK, ok, v1alpha2.HealthStatus{}))
c.Add(webservice)
return nil
}

View File

@@ -19,47 +19,56 @@ package components
import ( import (
"fmt" "fmt"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
) )
func GetComponentStatus(name string) (interface{}, error) { type ComponentsGetter interface {
GetComponentStatus(name string) (v1alpha2.ComponentStatus, error)
GetSystemHealthStatus() (v1alpha2.HealthStatus, error)
GetAllComponentsStatus() ([]v1alpha2.ComponentStatus, error)
}
type componentsGetter struct {
informers informers.SharedInformerFactory
}
func NewComponentsGetter(informers informers.SharedInformerFactory) ComponentsGetter {
return &componentsGetter{informers: informers}
}
func (c *componentsGetter) GetComponentStatus(name string) (v1alpha2.ComponentStatus, error) {
var service *corev1.Service var service *corev1.Service
var err error var err error
serviceLister := informers.SharedInformerFactory().Core().V1().Services().Lister()
for _, ns := range constants.SystemNamespaces { for _, ns := range constants.SystemNamespaces {
service, err = serviceLister.Services(ns).Get(name) service, err = c.informers.Core().V1().Services().Lister().Services(ns).Get(name)
if err == nil { if err == nil {
break break
} }
} }
if err != nil { if err != nil {
return nil, err return v1alpha2.ComponentStatus{}, err
} }
if len(service.Spec.Selector) == 0 { if len(service.Spec.Selector) == 0 {
return nil, fmt.Errorf("component %s has no selector", name) return v1alpha2.ComponentStatus{}, fmt.Errorf("component %s has no selector", name)
} }
podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister() pods, err := c.informers.Core().V1().Pods().Lister().Pods(service.Namespace).List(labels.SelectorFromValidatedSet(service.Spec.Selector))
pods, err := podLister.Pods(service.Namespace).List(labels.SelectorFromValidatedSet(service.Spec.Selector))
if err != nil { if err != nil {
return nil, err return v1alpha2.ComponentStatus{}, err
} }
component := models.ComponentStatus{ component := v1alpha2.ComponentStatus{
Name: service.Name, Name: service.Name,
Namespace: service.Namespace, Namespace: service.Namespace,
SelfLink: service.SelfLink, SelfLink: service.SelfLink,
@@ -86,21 +95,20 @@ func isAllContainersReady(pod *corev1.Pod) bool {
return true return true
} }
func GetSystemHealthStatus() (*models.HealthStatus, error) { func (c *componentsGetter) GetSystemHealthStatus() (v1alpha2.HealthStatus, error) {
status := &models.HealthStatus{} status := v1alpha2.HealthStatus{}
// get kubesphere-system components // get kubesphere-system components
components, err := GetAllComponentsStatus() components, err := c.GetAllComponentsStatus()
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
} }
status.KubeSphereComponents = components status.KubeSphereComponents = components
nodeLister := informers.SharedInformerFactory().Core().V1().Nodes().Lister()
// get node status // get node status
nodes, err := nodeLister.List(labels.Everything()) nodes, err := c.informers.Core().V1().Nodes().Lister().List(labels.Everything())
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
return status, nil return status, nil
@@ -116,7 +124,7 @@ func GetSystemHealthStatus() (*models.HealthStatus, error) {
} }
} }
} }
nodeStatus := models.NodeStatus{TotalNodes: totalNodes, HealthyNodes: healthyNodes} nodeStatus := v1alpha2.NodeStatus{TotalNodes: totalNodes, HealthyNodes: healthyNodes}
status.NodeStatus = nodeStatus status.NodeStatus = nodeStatus
@@ -124,16 +132,14 @@ func GetSystemHealthStatus() (*models.HealthStatus, error) {
} }
func GetAllComponentsStatus() ([]models.ComponentStatus, error) { func (c *componentsGetter) GetAllComponentsStatus() ([]v1alpha2.ComponentStatus, error) {
serviceLister := informers.SharedInformerFactory().Core().V1().Services().Lister()
podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister()
components := make([]models.ComponentStatus, 0) components := make([]v1alpha2.ComponentStatus, 0)
var err error var err error
for _, ns := range constants.SystemNamespaces { for _, ns := range constants.SystemNamespaces {
services, err := serviceLister.Services(ns).List(labels.Everything()) services, err := c.informers.Core().V1().Services().Lister().Services(ns).List(labels.Everything())
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
@@ -147,7 +153,7 @@ func GetAllComponentsStatus() ([]models.ComponentStatus, error) {
continue continue
} }
component := models.ComponentStatus{ component := v1alpha2.ComponentStatus{
Name: service.Name, Name: service.Name,
Namespace: service.Namespace, Namespace: service.Namespace,
SelfLink: service.SelfLink, SelfLink: service.SelfLink,
@@ -157,7 +163,7 @@ func GetAllComponentsStatus() ([]models.ComponentStatus, error) {
TotalBackends: 0, TotalBackends: 0,
} }
pods, err := podLister.Pods(ns).List(labels.SelectorFromValidatedSet(service.Spec.Selector)) pods, err := c.informers.Core().V1().Pods().Lister().Pods(ns).List(labels.SelectorFromValidatedSet(service.Spec.Selector))
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)

View File

@@ -0,0 +1,356 @@
package components
import (
"fmt"
"github.com/google/go-cmp/cmp"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes/fake"
"kubesphere.io/kubesphere/pkg/api/resource/v1alpha2"
"testing"
"time"
)
func service(name, namespace string, selector map[string]string) runtime.Object {
return &v1.Service{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: v1.ServiceSpec{
Selector: selector,
},
}
}
func pods(name, namespace string, labels map[string]string, healthPods, totalPods int) []runtime.Object {
var ps []runtime.Object
for index := 0; index < totalPods; index++ {
pod := &v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%d", name, index),
Namespace: namespace,
Labels: labels,
},
Status: v1.PodStatus{
Phase: v1.PodRunning,
ContainerStatuses: []v1.ContainerStatus{
{
Name: fmt.Sprintf("%s-%d", name, index),
Ready: true,
},
},
},
}
if index >= healthPods {
pod.Status.Phase = v1.PodPending
pod.Status.ContainerStatuses[0].Ready = false
}
ps = append(ps, pod)
}
return ps
}
func nodes(name string, healthNodes, totalNodes int) []runtime.Object {
var ns []runtime.Object
for index := 0; index < totalNodes; index++ {
node := &v1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%d", name, index),
},
Status: v1.NodeStatus{
Phase: v1.NodeRunning,
Conditions: []v1.NodeCondition{
{
Type: v1.NodeReady,
Status: v1.ConditionTrue,
},
},
},
}
if index >= healthNodes {
node.Status.Phase = v1.NodePending
node.Status.Conditions[0].Status = v1.ConditionFalse
}
ns = append(ns, node)
}
return ns
}
func TestGetSystemHealthStatus(t *testing.T) {
var tests = []struct {
description string
labels map[string]string
namespace string
name string
healthPods int
totalPods int
healthNodes int
totalNodes int
expected v1alpha2.HealthStatus
}{
{
"no backends",
map[string]string{"app": "foo"},
"kube-system",
"",
0,
0,
0,
0,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Namespace: "kube-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 0,
HealthyBackends: 0,
},
},
NodeStatus: v1alpha2.NodeStatus{},
},
},
{
"all healthy",
map[string]string{"app": "foo"},
"kubesphere-system",
"ks-apiserver",
2,
2,
2,
2,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 2,
HealthyBackends: 2,
},
},
NodeStatus: v1alpha2.NodeStatus{
TotalNodes: 2,
HealthyNodes: 2,
},
},
},
{
"all unhealthy",
map[string]string{"app": "foo"},
"kubesphere-system",
"ks-apiserver",
0,
2,
0,
2,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 2,
HealthyBackends: 0,
},
},
NodeStatus: v1alpha2.NodeStatus{
TotalNodes: 2,
HealthyNodes: 0,
},
},
},
{
"half healthy",
map[string]string{"app": "foo"},
"kubesphere-system",
"ks-apiserver",
2,
4,
2,
4,
v1alpha2.HealthStatus{
KubeSphereComponents: []v1alpha2.ComponentStatus{
{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 2,
},
},
NodeStatus: v1alpha2.NodeStatus{
TotalNodes: 4,
HealthyNodes: 2,
},
},
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
ps := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods)
svc := service(test.name, test.namespace, test.labels)
ns := nodes(test.name, test.healthNodes, test.totalNodes)
var objs []runtime.Object
objs = append(objs, ps...)
objs = append(objs, svc)
objs = append(objs, ns...)
client := fake.NewSimpleClientset(objs...)
informer := informers.NewSharedInformerFactory(client, time.Minute*10)
informer.Core().V1().Services().Informer().GetIndexer().Add(svc)
for _, obj := range ps {
informer.Core().V1().Pods().Informer().GetIndexer().Add(obj)
}
for _, obj := range ns {
informer.Core().V1().Nodes().Informer().GetIndexer().Add(obj)
}
c := NewComponentsGetter(informer)
healthStatus, err := c.GetSystemHealthStatus()
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(healthStatus, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
return
}
})
}
}
func TestGetComponentStatus(t *testing.T) {
var tests = []struct {
description string
name string
namespace string
labels map[string]string
healthPods int
totalPods int
expected v1alpha2.ComponentStatus
expectedError bool
}{
{
"no component",
"random",
"foo",
map[string]string{"app": "foo"},
2,
4,
v1alpha2.ComponentStatus{
Name: "",
Namespace: "",
SelfLink: "",
Label: nil,
StartedAt: time.Time{},
TotalBackends: 0,
HealthyBackends: 0,
},
true,
},
{
"all healthy",
"ks-apiserver",
"kubesphere-system",
map[string]string{"app": "foo"},
2,
4,
v1alpha2.ComponentStatus{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 2,
},
false,
},
{
"all unhealthy",
"ks-apiserver",
"kubesphere-system",
map[string]string{"app": "foo"},
0,
4,
v1alpha2.ComponentStatus{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 0,
},
false,
},
{
"half healthy",
"ks-apiserver",
"kubesphere-system",
map[string]string{"app": "foo"},
2,
4,
v1alpha2.ComponentStatus{
Name: "ks-apiserver",
Namespace: "kubesphere-system",
Label: map[string]string{"app": "foo"},
TotalBackends: 4,
HealthyBackends: 2,
},
false,
},
}
for _, test := range tests {
t.Run(test.description, func(t *testing.T) {
ps := pods(test.name, test.namespace, test.labels, test.healthPods, test.totalPods)
svc := service(test.name, test.namespace, test.labels)
var objs []runtime.Object
objs = append(objs, ps...)
objs = append(objs, svc)
client := fake.NewSimpleClientset(objs...)
informer := informers.NewSharedInformerFactory(client, time.Minute*10)
informer.Core().V1().Services().Informer().GetIndexer().Add(svc)
for _, obj := range ps {
informer.Core().V1().Pods().Informer().GetIndexer().Add(obj)
}
c := NewComponentsGetter(informer)
healthStatus, err := c.GetComponentStatus(test.name)
if err == nil && test.expectedError {
t.Fatalf("expected error while got nothing")
} else if err != nil && !test.expectedError {
t.Fatal(err)
}
if diff := cmp.Diff(healthStatus, test.expected); diff != "" {
t.Errorf("%T differ (-got, +want): %s", test.expected, diff)
return
}
})
}
}

View File

@@ -42,6 +42,12 @@ const (
cronJobLayout = "Monday, January 2, 2006 15:04:05 PM" cronJobLayout = "Monday, January 2, 2006 15:04:05 PM"
) )
type DevopsOperator interface {
}
type devopsOperator struct {
}
func GetPipeline(projectName, pipelineName string, req *http.Request) ([]byte, error) { func GetPipeline(projectName, pipelineName string, req *http.Request) ([]byte, error) {
devops, err := cs.ClientSets().Devops() devops, err := cs.ClientSets().Devops()
if err != nil { if err != nil {

View File

@@ -3,33 +3,37 @@ package devops
import ( import (
"code.cloudfoundry.org/bytefmt" "code.cloudfoundry.org/bytefmt"
"fmt" "fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
"github.com/emicklei/go-restful" "github.com/emicklei/go-restful"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/util/retry" "k8s.io/client-go/util/retry"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1" "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha1"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
"kubesphere.io/kubesphere/pkg/client/informers/externalversions"
"kubesphere.io/kubesphere/pkg/simple/client" "kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/simple/client/s3"
"mime/multipart" "mime/multipart"
"net/http" "net/http"
"reflect" "reflect"
"time"
) )
const ( const (
GetS2iBinaryURL = "http://ks-apiserver.kubesphere-system.svc/kapis/devops.kubesphere.io/v1alpha2/namespaces/%s/s2ibinaries/%s/file/%s" GetS2iBinaryURL = "http://ks-apiserver.kubesphere-system.svc/kapis/devops.kubesphere.io/v1alpha2/namespaces/%s/s2ibinaries/%s/file/%s"
) )
func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHeader) (*v1alpha1.S2iBinary, error) { type S2iBinaryUploader interface {
s3Client, err := client.ClientSets().S3() UploadBinary(name, namespace, md5 string, header *multipart.FileHeader) (*v1alpha1.S2iBinary, error)
if err != nil {
return nil, err
}
DownloadBinary(name, namespace, fileName string) (string, error)
}
type s2iBinaryUploader struct {
client versioned.Interface
informers externalversions.SharedInformerFactory
s3Client s3.Interface
}
func (s *s2iBinaryUploader) UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHeader) (*v1alpha1.S2iBinary, error) {
binFile, err := fileHeader.Open() binFile, err := fileHeader.Open()
if err != nil { if err != nil {
klog.Errorf("%+v", err) klog.Errorf("%+v", err)
@@ -37,7 +41,7 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead
} }
defer binFile.Close() defer binFile.Close()
origin, err := informers.KsSharedInformerFactory().Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name) origin, err := s.informers.Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name)
if err != nil { if err != nil {
klog.Errorf("%+v", err) klog.Errorf("%+v", err)
return nil, err return nil, err
@@ -58,7 +62,7 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead
} }
//Set status Uploading to lock resource //Set status Uploading to lock resource
uploading, err := SetS2iBinaryStatus(copy, v1alpha1.StatusUploading) uploading, err := s.SetS2iBinaryStatus(copy, v1alpha1.StatusUploading)
if err != nil { if err != nil {
err := restful.NewError(http.StatusConflict, fmt.Sprintf("could not set status: %+v", err)) err := restful.NewError(http.StatusConflict, fmt.Sprintf("could not set status: %+v", err))
klog.Error(err) klog.Error(err)
@@ -71,51 +75,53 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead
copy.Spec.FileName = fileHeader.Filename copy.Spec.FileName = fileHeader.Filename
copy.Spec.DownloadURL = fmt.Sprintf(GetS2iBinaryURL, namespace, name, copy.Spec.FileName) copy.Spec.DownloadURL = fmt.Sprintf(GetS2iBinaryURL, namespace, name, copy.Spec.FileName)
s3session := s3Client.Session() /*
if s3session == nil { TODO: upload binary file use s3.Interface
err := fmt.Errorf("could not connect to s2i s3") s3session := s3Client.Session()
klog.Error(err) if s3session == nil {
_, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase) err := fmt.Errorf("could not connect to s2i s3")
if serr != nil { klog.Error(err)
klog.Error(serr) _, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
return nil, err if serr != nil {
} klog.Error(serr)
return nil, err
}
uploader := s3manager.NewUploader(s3session, func(uploader *s3manager.Uploader) {
uploader.PartSize = 5 * bytefmt.MEGABYTE
uploader.LeavePartsOnError = true
})
_, err = uploader.Upload(&s3manager.UploadInput{
Bucket: s3Client.Bucket(),
Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)),
Body: binFile,
ContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", copy.Spec.FileName)),
})
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case s3.ErrCodeNoSuchBucket:
klog.Error(err)
_, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
if serr != nil {
klog.Error(serr)
}
return nil, err
default:
klog.Error(err)
_, serr := SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed)
if serr != nil {
klog.Error(serr)
}
return nil, err return nil, err
} }
return nil, err
} }
klog.Error(err) uploader := s3manager.NewUploader(s3session, func(uploader *s3manager.Uploader) {
return nil, err uploader.PartSize = 5 * bytefmt.MEGABYTE
} uploader.LeavePartsOnError = true
})
_, err = uploader.Upload(&s3manager.UploadInput{
Bucket: s3Client.Bucket(),
Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)),
Body: binFile,
ContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", copy.Spec.FileName)),
})
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case s3.ErrCodeNoSuchBucket:
klog.Error(err)
_, serr := SetS2iBinaryStatusWithRetry(copy, origin.Status.Phase)
if serr != nil {
klog.Error(serr)
}
return nil, err
default:
klog.Error(err)
_, serr := SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusUploadFailed)
if serr != nil {
klog.Error(serr)
}
return nil, err
}
}
klog.Error(err)
return nil, err
}
*/
if copy.Spec.UploadTimeStamp == nil { if copy.Spec.UploadTimeStamp == nil {
copy.Spec.UploadTimeStamp = new(metav1.Time) copy.Spec.UploadTimeStamp = new(metav1.Time)
} }
@@ -126,7 +132,7 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead
return nil, err return nil, err
} }
copy, err = SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusReady) copy, err = s.SetS2iBinaryStatusWithRetry(copy, v1alpha1.StatusReady)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
@@ -134,46 +140,47 @@ func UploadS2iBinary(namespace, name, md5 string, fileHeader *multipart.FileHead
return copy, nil return copy, nil
} }
func DownloadS2iBinary(namespace, name, fileName string) (string, error) { func (s *s2iBinaryUploader) DownloadS2iBinary(namespace, name, fileName string) (string, error) {
s3Client, err := client.ClientSets().S3()
if err != nil {
return "", err
}
origin, err := informers.KsSharedInformerFactory().Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name) origin, err := s.informers.Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(namespace).Get(name)
if err != nil { if err != nil {
klog.Errorf("%+v", err) klog.Errorf("%+v", err)
return "", err return "", err
} }
if origin.Spec.FileName != fileName { if origin.Spec.FileName != fileName {
err := fmt.Errorf("could not fould file %s", fileName) err := fmt.Errorf("could not fould file %s", fileName)
klog.Error(err) klog.Error(err)
return "", err return "", err
} }
if origin.Status.Phase != v1alpha1.StatusReady { if origin.Status.Phase != v1alpha1.StatusReady {
err := restful.NewError(http.StatusBadRequest, "file is not ready, please try later") err := restful.NewError(http.StatusBadRequest, "file is not ready, please try later")
klog.Error(err) klog.Error(err)
return "", err return "", err
} }
req, _ := s3Client.Client().GetObjectRequest(&s3.GetObjectInput{ /*
Bucket: s3Client.Bucket(), TODO: get download url of requested binary
Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)), req, _ := s.s3Client.Client().GetObjectRequest(&s3.GetObjectInput{
ResponseContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", origin.Spec.FileName)), Bucket: s3Client.Bucket(),
}) Key: aws.String(fmt.Sprintf("%s-%s", namespace, name)),
url, err := req.Presign(5 * time.Minute) ResponseContentDisposition: aws.String(fmt.Sprintf("attachment; filename=\"%s\"", origin.Spec.FileName)),
if err != nil { })
klog.Error(err) url, err := req.Presign(5 * time.Minute)
return "", err if err != nil {
} klog.Error(err)
return url, nil return "", err
}
*/
return "", nil
} }
func SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) { func (s *s2iBinaryUploader) SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) {
copy := s2ibin.DeepCopy() copy := s2ibin.DeepCopy()
copy.Status.Phase = status copy.Status.Phase = status
copy, err := client.ClientSets().K8s().KubeSphere().DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(copy) copy, err := s.client.DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(copy)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
@@ -181,18 +188,18 @@ func SetS2iBinaryStatus(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2
return copy, nil return copy, nil
} }
func SetS2iBinaryStatusWithRetry(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) { func (s *s2iBinaryUploader) SetS2iBinaryStatusWithRetry(s2ibin *v1alpha1.S2iBinary, status string) (*v1alpha1.S2iBinary, error) {
var bin *v1alpha1.S2iBinary var bin *v1alpha1.S2iBinary
var err error var err error
err = retry.RetryOnConflict(retry.DefaultRetry, func() error { err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
bin, err = informers.KsSharedInformerFactory().Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(s2ibin.Namespace).Get(s2ibin.Name) bin, err = s.informers.Devops().V1alpha1().S2iBinaries().Lister().S2iBinaries(s2ibin.Namespace).Get(s2ibin.Name)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return err return err
} }
bin.Status.Phase = status bin.Status.Phase = status
bin, err = client.ClientSets().K8s().KubeSphere().DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(bin) bin, err = s.client.DevopsV1alpha1().S2iBinaries(s2ibin.Namespace).Update(bin)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return err return err

View File

@@ -7,7 +7,7 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing/transport/http" "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
"gopkg.in/src-d/go-git.v4/storage/memory" "gopkg.in/src-d/go-git.v4/storage/memory"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/informers" "k8s.io/client-go/informers"
) )
type AuthInfo struct { type AuthInfo struct {
@@ -15,12 +15,23 @@ type AuthInfo struct {
SecretRef *corev1.SecretReference `json:"secretRef,omitempty" description:"auth secret reference"` SecretRef *corev1.SecretReference `json:"secretRef,omitempty" description:"auth secret reference"`
} }
func GitReadVerify(namespace string, authInfo AuthInfo) error { type GitVerifier interface {
username := "" VerifyGitCredential(remoteUrl, namespace, secretName string) error
password := "" }
if authInfo.SecretRef != nil {
secret, err := informers.SharedInformerFactory().Core().V1().Secrets().Lister(). type gitVerifier struct {
Secrets(authInfo.SecretRef.Namespace).Get(authInfo.SecretRef.Name) informers informers.SharedInformerFactory
}
func NewGitVerifier(informers informers.SharedInformerFactory) GitVerifier {
return &gitVerifier{informers: informers}
}
func (c *gitVerifier) VerifyGitCredential(remoteUrl, namespace, secretName string) error {
var username, password string
if len(secretName) > 0 {
secret, err := c.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(secretName)
if err != nil { if err != nil {
return err return err
} }
@@ -36,10 +47,10 @@ func GitReadVerify(namespace string, authInfo AuthInfo) error {
password = string(passwordBytes) password = string(passwordBytes)
} }
return gitReadVerifyWithBasicAuth(string(username), string(password), authInfo.RemoteUrl) return c.gitReadVerifyWithBasicAuth(username, password, remoteUrl)
} }
func gitReadVerifyWithBasicAuth(username string, password string, remote string) error { func (c *gitVerifier) gitReadVerifyWithBasicAuth(username string, password string, remote string) error {
r, _ := git.Init(memory.NewStorage(), nil) r, _ := git.Init(memory.NewStorage(), nil)
// Add a new remote, with the default fetch refspec // Add a new remote, with the default fetch refspec

View File

@@ -34,8 +34,10 @@ func TestGitReadVerifyWithBasicAuth(t *testing.T) {
"remote": "git@fdsfs41342`@@@2414!!!!github.com:kubesphere/kubesphere.git", "remote": "git@fdsfs41342`@@@2414!!!!github.com:kubesphere/kubesphere.git",
}, },
} }
verifier := gitVerifier{informers: nil}
for _, item := range shouldSuccess { for _, item := range shouldSuccess {
err := gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"]) err := verifier.gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"])
if err != nil { if err != nil {
t.Errorf("should could access repo [%s] with %s:%s, %v", item["username"], item["password"], item["remote"], err) t.Errorf("should could access repo [%s] with %s:%s, %v", item["username"], item["password"], item["remote"], err)
@@ -43,7 +45,7 @@ func TestGitReadVerifyWithBasicAuth(t *testing.T) {
} }
for _, item := range shouldFailed { for _, item := range shouldFailed {
err := gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"]) err := verifier.gitReadVerifyWithBasicAuth(item["username"], item["password"], item["remote"])
if err == nil { if err == nil {
t.Errorf("should could access repo [%s] with %s:%s ", item["username"], item["password"], item["remote"]) t.Errorf("should could access repo [%s] with %s:%s ", item["username"], item["password"], item["remote"])
} }

View File

@@ -26,12 +26,13 @@ import (
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/apiserver/resources"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam/policy" "kubesphere.io/kubesphere/pkg/models/iam/policy"
"kubesphere.io/kubesphere/pkg/models/kubectl" "kubesphere.io/kubesphere/pkg/models/kubectl"
"kubesphere.io/kubesphere/pkg/models/resources" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/simple/client" "kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/k8sutil"
@@ -354,7 +355,7 @@ func ListClusterRoleUsers(clusterRoleName string, conditions *params.Conditions,
switch orderBy { switch orderBy {
default: default:
fallthrough fallthrough
case resources.Name: case v1alpha2.Name:
return strings.Compare(users[i].Username, users[j].Username) <= 0 return strings.Compare(users[i].Username, users[j].Username) <= 0
} }
}) })
@@ -401,13 +402,13 @@ func RoleUsers(namespace string, roleName string) ([]*models.User, error) {
} }
func ListRoles(namespace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { func ListRoles(namespace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
return resources.ListResources(namespace, resources.Roles, conditions, orderBy, reverse, limit, offset) return resources.ListResources(namespace, v1alpha2.Roles, conditions, orderBy, reverse, limit, offset)
} }
func ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { func ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
conditions.Match[resources.OwnerName] = workspace conditions.Match[v1alpha2.OwnerName] = workspace
conditions.Match[resources.OwnerKind] = "Workspace" conditions.Match[v1alpha2.OwnerKind] = "Workspace"
result, err := resources.ListResources("", resources.ClusterRoles, conditions, orderBy, reverse, limit, offset) result, err := resources.ListResources("", v1alpha2.ClusterRoles, conditions, orderBy, reverse, limit, offset)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -424,7 +425,7 @@ func ListWorkspaceRoles(workspace string, conditions *params.Conditions, orderBy
} }
func ListClusterRoles(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) { func ListClusterRoles(conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
return resources.ListResources("", resources.ClusterRoles, conditions, orderBy, reverse, limit, offset) return resources.ListResources("", v1alpha2.ClusterRoles, conditions, orderBy, reverse, limit, offset)
} }
func NamespaceUsers(namespaceName string) ([]*models.User, error) { func NamespaceUsers(namespaceName string) ([]*models.User, error) {

View File

@@ -799,8 +799,8 @@ func deleteUserInDevOps(username string) error {
devopsDb, err := clientset.ClientSets().MySQL() devopsDb, err := clientset.ClientSets().MySQL()
if err != nil { if err != nil {
if _, ok := err.(clientset.ClientSetNotEnabledError); ok { if err == clientset.ErrClientSetNotEnabled {
klog.Warning("devops client is not enable") klog.Warning("mysql is not enable")
return nil return nil
} }
return err return err
@@ -808,11 +808,10 @@ func deleteUserInDevOps(username string) error {
dp, err := clientset.ClientSets().Devops() dp, err := clientset.ClientSets().Devops()
if err != nil { if err != nil {
if _, ok := err.(clientset.ClientSetNotEnabledError); ok { if err == clientset.ErrClientSetNotEnabled {
klog.Warning("devops client is not enable") klog.Warning("devops client is not enable")
return nil return nil
} }
return err return err
} }

View File

@@ -28,7 +28,6 @@ import (
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/api/logging/v1alpha2" "kubesphere.io/kubesphere/pkg/api/logging/v1alpha2"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/informers"
fb "kubesphere.io/kubesphere/pkg/simple/client/fluentbit"
"net/http" "net/http"
"strings" "strings"
"time" "time"

View File

@@ -18,10 +18,6 @@
package log package log
import (
fb "kubesphere.io/kubesphere/pkg/simple/client/fluentbit"
)
type FluentbitOutputsResult struct { type FluentbitOutputsResult struct {
Status int `json:"status" description:"response status"` Status int `json:"status" description:"response status"`
Error string `json:"error,omitempty" description:"debug information"` Error string `json:"error,omitempty" description:"debug information"`

View File

@@ -1,279 +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 nodes
import (
"fmt"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/simple/client"
"math"
"strings"
"time"
appsv1 "k8s.io/api/apps/v1"
"k8s.io/api/core/v1"
policy "k8s.io/api/policy/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
)
func DrainNode(nodename string) (err error) {
k8sclient := client.ClientSets().K8s().Kubernetes()
node, err := k8sclient.CoreV1().Nodes().Get(nodename, metav1.GetOptions{})
if err != nil {
return err
}
if node.Spec.Unschedulable {
return fmt.Errorf("node %s have been drained", nodename)
}
data := []byte(" {\"spec\":{\"unschedulable\":true}}")
_, err = k8sclient.CoreV1().Nodes().Patch(nodename, types.StrategicMergePatchType, data)
if err != nil {
return err
}
donech := make(chan bool)
errch := make(chan error)
go drainEviction(nodename, donech, errch)
for {
select {
case err := <-errch:
return err
case <-donech:
return nil
}
}
}
func drainEviction(nodename string, donech chan bool, errch chan error) {
k8sclient := client.ClientSets().K8s().Kubernetes()
var options metav1.ListOptions
pods := make([]v1.Pod, 0)
options.FieldSelector = "spec.nodeName=" + nodename
podList, err := k8sclient.CoreV1().Pods("").List(options)
if err != nil {
klog.Fatal(err)
errch <- err
}
options.FieldSelector = ""
daemonsetList, err := k8sclient.AppsV1().DaemonSets("").List(options)
if err != nil {
klog.Fatal(err)
errch <- err
}
// remove mirror pod static pod
if len(podList.Items) > 0 {
for _, pod := range podList.Items {
if !containDaemonset(pod, *daemonsetList) {
//static or mirror pod
if isStaticPod(&pod) || isMirrorPod(&pod) {
continue
} else {
pods = append(pods, pod)
}
}
}
}
if len(pods) == 0 {
donech <- true
} else {
//create eviction
getPodFn := func(namespace, name string) (*v1.Pod, error) {
return k8sclient.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
}
evicerr := evictPods(pods, 0, getPodFn)
if evicerr == nil {
donech <- true
} else {
klog.Fatal(evicerr)
errch <- err
}
}
}
func getPodSource(pod *v1.Pod) (string, error) {
if pod.Annotations != nil {
if source, ok := pod.Annotations["kubernetes.io/config.source"]; ok {
return source, nil
}
}
return "", fmt.Errorf("cannot get source of pod %q", pod.UID)
}
func isStaticPod(pod *v1.Pod) bool {
source, err := getPodSource(pod)
return err == nil && source != "api"
}
func isMirrorPod(pod *v1.Pod) bool {
_, ok := pod.Annotations[v1.MirrorPodAnnotationKey]
return ok
}
func containDaemonset(pod v1.Pod, daemonsetList appsv1.DaemonSetList) bool {
flag := false
for _, daemonset := range daemonsetList.Items {
if strings.Contains(pod.Name, daemonset.Name) {
flag = true
}
}
return flag
}
func evictPod(pod v1.Pod, GracePeriodSeconds int) error {
k8sclient := client.ClientSets().K8s().Kubernetes()
deleteOptions := &metav1.DeleteOptions{}
if GracePeriodSeconds >= 0 {
gracePeriodSeconds := int64(GracePeriodSeconds)
deleteOptions.GracePeriodSeconds = &gracePeriodSeconds
}
var eviction policy.Eviction
eviction.Kind = "Eviction"
eviction.APIVersion = "policy/v1beta1"
eviction.Namespace = pod.Namespace
eviction.Name = pod.Name
eviction.DeleteOptions = deleteOptions
err := k8sclient.CoreV1().Pods(pod.Namespace).Evict(&eviction)
if err != nil {
return err
}
return nil
}
func evictPods(pods []v1.Pod, GracePeriodSeconds int, getPodFn func(namespace, name string) (*v1.Pod, error)) error {
doneCh := make(chan bool, len(pods))
errCh := make(chan error, 1)
for _, pod := range pods {
go func(pod v1.Pod, doneCh chan bool, errCh chan error) {
var err error
var count int
for {
err = evictPod(pod, GracePeriodSeconds)
if err == nil {
count++
if count > 2 {
break
} else {
continue
}
} else if apierrors.IsNotFound(err) {
count = 0
doneCh <- true
klog.Info(fmt.Sprintf("pod %s evict", pod.Name))
return
} else if apierrors.IsTooManyRequests(err) {
count = 0
time.Sleep(5 * time.Second)
} else {
count = 0
errCh <- fmt.Errorf("error when evicting pod %q: %v", pod.Name, err)
return
}
}
podArray := []v1.Pod{pod}
_, err = waitForDelete(podArray, time.Second, time.Duration(math.MaxInt64), getPodFn)
if err == nil {
doneCh <- true
klog.Info(fmt.Sprintf("pod %s delete", pod.Name))
} else {
errCh <- fmt.Errorf("error when waiting for pod %q terminating: %v", pod.Name, err)
}
}(pod, doneCh, errCh)
}
Timeout := 300 * power(10, 9)
doneCount := 0
// 0 timeout means infinite, we use MaxInt64 to represent it.
var globalTimeout time.Duration
if Timeout == 0 {
globalTimeout = time.Duration(math.MaxInt64)
} else {
globalTimeout = time.Duration(Timeout)
}
for {
select {
case err := <-errCh:
return err
case <-doneCh:
doneCount++
if doneCount == len(pods) {
return nil
}
case <-time.After(globalTimeout):
return fmt.Errorf("drain did not complete within %v", globalTimeout)
}
}
}
func waitForDelete(pods []v1.Pod, interval, timeout time.Duration, getPodFn func(string, string) (*v1.Pod, error)) ([]v1.Pod, error) {
err := wait.PollImmediate(interval, timeout, func() (bool, error) {
var pendingPods []v1.Pod
for i, pod := range pods {
p, err := getPodFn(pod.Namespace, pod.Name)
if apierrors.IsNotFound(err) || (p != nil && p.ObjectMeta.UID != pod.ObjectMeta.UID) {
continue
} else if err != nil {
return false, err
} else {
pendingPods = append(pendingPods, pods[i])
}
}
pods = pendingPods
if len(pendingPods) > 0 {
return false, nil
}
return true, nil
})
return pods, err
}
func power(x int64, n int) int64 {
var res int64 = 1
for n != 0 {
res *= x
n--
}
return res
}

View File

@@ -28,11 +28,10 @@ import (
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/informers"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/models" "kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
cs "kubesphere.io/kubesphere/pkg/simple/client" cs "kubesphere.io/kubesphere/pkg/simple/client"
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix" "kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
@@ -40,6 +39,26 @@ import (
"strings" "strings"
) )
type Interface interface {
List(conditions *params.Conditions, limit, offset int, orderBy string, reverse bool) (*models.PageableResponse, error)
Get(namespace, clusterID string) (*Application, error)
Create(namespace string, request CreateClusterRequest) error
Patch(request ModifyClusterAttributesRequest) error
Delete(id string) error
}
type applicationOperator struct {
informers informers.SharedInformerFactory
opClient pb.ClusterManagerClient
}
func NewApplicaitonOperator(informers informers.SharedInformerFactory, client pb.ClusterManagerClient) Interface {
return &applicationOperator{
informers: informers,
opClient: client,
}
}
type Application struct { type Application struct {
Name string `json:"name" description:"application name"` Name string `json:"name" description:"application name"`
Cluster *Cluster `json:"cluster,omitempty" description:"application cluster info"` Cluster *Cluster `json:"cluster,omitempty" description:"application cluster info"`
@@ -56,7 +75,7 @@ type workLoads struct {
Daemonsets []appsv1.DaemonSet `json:"daemonsets,omitempty" description:"daemonset list"` Daemonsets []appsv1.DaemonSet `json:"daemonsets,omitempty" description:"daemonset list"`
} }
func ListApplications(conditions *params.Conditions, limit, offset int, orderBy string, reverse bool) (*models.PageableResponse, error) { func (c *applicationOperator) List(conditions *params.Conditions, limit, offset int, orderBy string, reverse bool) (*models.PageableResponse, error) {
client, err := cs.ClientSets().OpenPitrix() client, err := cs.ClientSets().OpenPitrix()
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
@@ -92,7 +111,7 @@ func ListApplications(conditions *params.Conditions, limit, offset int, orderBy
result := models.PageableResponse{TotalCount: int(resp.TotalCount)} result := models.PageableResponse{TotalCount: int(resp.TotalCount)}
result.Items = make([]interface{}, 0) result.Items = make([]interface{}, 0)
for _, cluster := range resp.ClusterSet { for _, cluster := range resp.ClusterSet {
app, err := describeApplication(cluster) app, err := c.describeApplication(cluster)
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
return nil, err return nil, err
@@ -103,7 +122,7 @@ func ListApplications(conditions *params.Conditions, limit, offset int, orderBy
return &result, nil return &result, nil
} }
func describeApplication(cluster *pb.Cluster) (*Application, error) { func (c *applicationOperator) describeApplication(cluster *pb.Cluster) (*Application, error) {
op, err := cs.ClientSets().OpenPitrix() op, err := cs.ClientSets().OpenPitrix()
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
@@ -131,15 +150,9 @@ func describeApplication(cluster *pb.Cluster) (*Application, error) {
return &app, nil return &app, nil
} }
func DescribeApplication(namespace string, clusterId string) (*Application, error) { func (c *applicationOperator) Get(namespace string, clusterId string) (*Application, error) {
client, err := cs.ClientSets().OpenPitrix() clusters, err := c.opClient.DescribeClusters(openpitrix.SystemContext(), &pb.DescribeClustersRequest{ClusterId: []string{clusterId}, Limit: 1})
if err != nil {
klog.Error(err)
return nil, err
}
clusters, err := client.Cluster().DescribeClusters(openpitrix.SystemContext(), &pb.DescribeClustersRequest{ClusterId: []string{clusterId}, Limit: 1})
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
@@ -154,26 +167,26 @@ func DescribeApplication(namespace string, clusterId string) (*Application, erro
klog.Errorln(err) klog.Errorln(err)
return nil, err return nil, err
} }
app, err := describeApplication(cluster) app, err := c.describeApplication(cluster)
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
return nil, err return nil, err
} }
workloads, err := getWorkLoads(namespace, cluster.ClusterRoleSet) workloads, err := c.getWorkLoads(namespace, cluster.ClusterRoleSet)
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)
return nil, err return nil, err
} }
app.WorkLoads = workloads app.WorkLoads = workloads
workloadLabels := getLabels(namespace, app.WorkLoads) workloadLabels := c.getLabels(namespace, app.WorkLoads)
app.Services = getSvcs(namespace, workloadLabels) app.Services = c.getSvcs(namespace, workloadLabels)
app.Ingresses = getIng(namespace, app.Services) app.Ingresses = c.getIng(namespace, app.Services)
return app, nil return app, nil
} }
func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, error) { func (c *applicationOperator) getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads, error) {
var works workLoads var works workLoads
for _, clusterRole := range clusterRoles { for _, clusterRole := range clusterRoles {
@@ -182,7 +195,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads,
if strings.HasSuffix(workLoadName, openpitrix.DeploySuffix) { if strings.HasSuffix(workLoadName, openpitrix.DeploySuffix) {
name := strings.Split(workLoadName, openpitrix.DeploySuffix)[0] name := strings.Split(workLoadName, openpitrix.DeploySuffix)[0]
item, err := informers.SharedInformerFactory().Apps().V1().Deployments().Lister().Deployments(namespace).Get(name) item, err := c.informers.Apps().V1().Deployments().Lister().Deployments(namespace).Get(name)
if err != nil { if err != nil {
// app not ready // app not ready
@@ -199,7 +212,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads,
if strings.HasSuffix(workLoadName, openpitrix.DaemonSuffix) { if strings.HasSuffix(workLoadName, openpitrix.DaemonSuffix) {
name := strings.Split(workLoadName, openpitrix.DaemonSuffix)[0] name := strings.Split(workLoadName, openpitrix.DaemonSuffix)[0]
item, err := informers.SharedInformerFactory().Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name) item, err := c.informers.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(name)
if err != nil { if err != nil {
// app not ready // app not ready
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
@@ -214,7 +227,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads,
if strings.HasSuffix(workLoadName, openpitrix.StateSuffix) { if strings.HasSuffix(workLoadName, openpitrix.StateSuffix) {
name := strings.Split(workLoadName, openpitrix.StateSuffix)[0] name := strings.Split(workLoadName, openpitrix.StateSuffix)[0]
item, err := informers.SharedInformerFactory().Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name) item, err := c.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(name)
if err != nil { if err != nil {
// app not ready // app not ready
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
@@ -231,8 +244,7 @@ func getWorkLoads(namespace string, clusterRoles []*pb.ClusterRole) (*workLoads,
return &works, nil return &works, nil
} }
func getLabels(namespace string, workloads *workLoads) *[]map[string]string { func (c *applicationOperator) getLabels(namespace string, workloads *workLoads) *[]map[string]string {
k8sClient := cs.ClientSets().K8s().Kubernetes()
var workloadLabels []map[string]string var workloadLabels []map[string]string
if workloads == nil { if workloads == nil {
@@ -240,7 +252,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string {
} }
for _, workload := range workloads.Deployments { for _, workload := range workloads.Deployments {
deploy, err := k8sClient.AppsV1().Deployments(namespace).Get(workload.Name, metav1.GetOptions{}) deploy, err := c.informers.Apps().V1().Deployments().Lister().Deployments(namespace).Get(workload.Name)
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
continue continue
} }
@@ -248,7 +260,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string {
} }
for _, workload := range workloads.Daemonsets { for _, workload := range workloads.Daemonsets {
daemonset, err := k8sClient.AppsV1().DaemonSets(namespace).Get(workload.Name, metav1.GetOptions{}) daemonset, err := c.informers.Apps().V1().DaemonSets().Lister().DaemonSets(namespace).Get(workload.Name)
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
continue continue
} }
@@ -256,7 +268,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string {
} }
for _, workload := range workloads.Statefulsets { for _, workload := range workloads.Statefulsets {
statefulset, err := k8sClient.AppsV1().StatefulSets(namespace).Get(workload.Name, metav1.GetOptions{}) statefulset, err := c.informers.Apps().V1().StatefulSets().Lister().StatefulSets(namespace).Get(workload.Name)
if errors.IsNotFound(err) { if errors.IsNotFound(err) {
continue continue
} }
@@ -266,7 +278,7 @@ func getLabels(namespace string, workloads *workLoads) *[]map[string]string {
return &workloadLabels return &workloadLabels
} }
func isExist(svcs []v1.Service, svc v1.Service) bool { func (c *applicationOperator) isExist(svcs []v1.Service, svc v1.Service) bool {
for _, item := range svcs { for _, item := range svcs {
if item.Name == svc.Name && item.Namespace == svc.Namespace { if item.Name == svc.Name && item.Namespace == svc.Namespace {
return true return true
@@ -275,7 +287,7 @@ func isExist(svcs []v1.Service, svc v1.Service) bool {
return false return false
} }
func getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service { func (c *applicationOperator) getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service {
if len(*workLoadLabels) == 0 { if len(*workLoadLabels) == 0 {
return nil return nil
} }
@@ -288,7 +300,7 @@ func getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service
klog.Errorf("get app's svc failed, reason: %v", err) klog.Errorf("get app's svc failed, reason: %v", err)
} }
for _, item := range svcs.Items { for _, item := range svcs.Items {
if !isExist(services, item) { if !c.isExist(services, item) {
services = append(services, item) services = append(services, item)
} }
} }
@@ -297,21 +309,23 @@ func getSvcs(namespace string, workLoadLabels *[]map[string]string) []v1.Service
return services return services
} }
func getIng(namespace string, services []v1.Service) []v1beta1.Ingress { func (c *applicationOperator) getIng(namespace string, services []v1.Service) []v1beta1.Ingress {
if services == nil { if services == nil {
return nil return nil
} }
var ings []v1beta1.Ingress var ings []v1beta1.Ingress
for _, svc := range services { for _, svc := range services {
result, err := resources.ListResources(namespace, "ingress", &params.Conditions{Fuzzy: map[string]string{"serviceName": svc.Name}}, "", false, -1, 0) ingresses, err := c.informers.Extensions().V1beta1().Ingresses().Lister().Ingresses(namespace).List(labels.Everything())
if err != nil { if err != nil {
klog.Errorln(err) klog.Error(err)
return nil return ings
} }
for _, i := range result.Items { for _, ingress := range ingresses {
ingress := i.(*v1beta1.Ingress) if ingress.Spec.Backend.ServiceName != svc.Name {
continue
}
exist := false exist := false
var tmpRules []v1beta1.IngressRule var tmpRules []v1beta1.IngressRule
@@ -322,7 +336,6 @@ func getIng(namespace string, services []v1.Service) []v1beta1.Ingress {
tmpRules = append(tmpRules, rule) tmpRules = append(tmpRules, rule)
} }
} }
} }
if exist { if exist {
@@ -337,8 +350,8 @@ func getIng(namespace string, services []v1.Service) []v1beta1.Ingress {
return ings return ings
} }
func CreateApplication(namespace string, request CreateClusterRequest) error { func (c *applicationOperator) Create(namespace string, request CreateClusterRequest) error {
ns, err := informers.SharedInformerFactory().Core().V1().Namespaces().Lister().Get(namespace) ns, err := c.informers.Core().V1().Namespaces().Lister().Get(namespace)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return err return err
@@ -372,7 +385,7 @@ func CreateApplication(namespace string, request CreateClusterRequest) error {
return nil return nil
} }
func PatchApplication(request *ModifyClusterAttributesRequest) error { func (c *applicationOperator) Patch(request ModifyClusterAttributesRequest) error {
op, err := cs.ClientSets().OpenPitrix() op, err := cs.ClientSets().OpenPitrix()
if err != nil { if err != nil {
@@ -397,15 +410,8 @@ func PatchApplication(request *ModifyClusterAttributesRequest) error {
return nil return nil
} }
func DeleteApplication(clusterId string) error { func (c *applicationOperator) Delete(clusterId string) error {
client, err := cs.ClientSets().OpenPitrix() _, err := c.opClient.DeleteClusters(openpitrix.SystemContext(), &pb.DeleteClustersRequest{ClusterId: []string{clusterId}, Force: &wrappers.BoolValue{Value: true}})
if err != nil {
klog.Error(err)
return err
}
_, err = client.Cluster().DeleteClusters(openpitrix.SystemContext(), &pb.DeleteClustersRequest{ClusterId: []string{clusterId}, Force: &wrappers.BoolValue{Value: true}})
if err != nil { if err != nil {
klog.Errorln(err) klog.Errorln(err)

View File

@@ -22,11 +22,10 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/informers"
"k8s.io/klog" "k8s.io/klog"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/resources"
"kubesphere.io/kubesphere/pkg/server/params"
) )
const ( const (
@@ -42,71 +41,69 @@ const (
s2iBuilders = "count/s2ibuilders.devops.kubesphere.io" s2iBuilders = "count/s2ibuilders.devops.kubesphere.io"
) )
type NamespacedResourceQuota struct { var supportedResources = map[string]schema.GroupVersionResource{
Namespace string `json:"namespace,omitempty"` deploymentsKey: {Group: "apps", Version: "v1", Resource: "deployments"},
daemonsetsKey: {Group: "apps", Version: "v1", Resource: "daemonsets"},
Data struct { statefulsetsKey: {Group: "apps", Version: "v1", Resource: "statefulsets"},
v1.ResourceQuotaStatus podsKey: {Group: "", Version: "v1", Resource: "pods"},
servicesKey: {Group: "", Version: "v1", Resource: "services"},
// quota left status, do the math on the side, cause it's persistentvolumeclaimsKey: {Group: "", Version: "v1", Resource: "persistentvolumeclaims"},
// a lot easier with go-client library ingressKey: {Group: "extensions", Version: "v1beta1", Resource: "ingresses"},
Left v1.ResourceList `json:"left,omitempty"` jobsKey: {Group: "batch", Version: "v1", Resource: "jobs"},
} `json:"data,omitempty"` cronJobsKey: {Group: "batch", Version: "v1beta1", Resource: "cronjobs"},
s2iBuilders: {Group: "devops.kubesphere.io", Version: "v1alpha1", Resource: "s2ibuilders"},
} }
var ( type ResourceQuotaGetter interface {
resourceMap = map[string]string{ GetClusterQuota() (*api.ResourceQuota, error)
daemonsetsKey: resources.DaemonSets, GetNamespaceQuota(namespace string) (*api.NamespacedResourceQuota, error)
deploymentsKey: resources.Deployments, }
ingressKey: resources.Ingresses,
servicesKey: resources.Services,
statefulsetsKey: resources.StatefulSets,
persistentvolumeclaimsKey: resources.PersistentVolumeClaims,
podsKey: resources.Pods,
jobsKey: resources.Jobs,
cronJobsKey: resources.CronJobs,
s2iBuilders: resources.S2iBuilders,
}
)
func getUsage(namespace, resource string) (int, error) { type resourceQuotaGetter struct {
var result *models.PageableResponse informers informers.SharedInformerFactory
var err error }
if resource == resources.Namespaces || resource == resources.StorageClasses {
result, err = resources.ListResources("", resource, &params.Conditions{}, "", false, 1, 0)
} else {
result, err = resources.ListResources(namespace, resource, &params.Conditions{}, "", false, 1, 0)
}
func NewResourceQuotaGetter(informers informers.SharedInformerFactory) ResourceQuotaGetter {
return &resourceQuotaGetter{informers: informers}
}
func (c *resourceQuotaGetter) getUsage(namespace, resource string) (int, error) {
genericInformer, err := c.informers.ForResource(supportedResources[resource])
if err != nil {
// we deliberately ignore error if trying to get non existed resource
return 0, nil
}
result, err := genericInformer.Lister().ByNamespace(namespace).List(labels.Everything())
if err != nil { if err != nil {
klog.Error(err)
return 0, err return 0, err
} }
return result.TotalCount, nil return len(result), nil
} }
// no one use this api anymore marked as deprecated // no one use this api anymore marked as deprecated
func GetClusterQuotas() (*models.ResourceQuota, error) { func (c *resourceQuotaGetter) GetClusterQuota() (*api.ResourceQuota, error) {
quota := v1.ResourceQuotaStatus{Hard: make(v1.ResourceList), Used: make(v1.ResourceList)} quota := v1.ResourceQuotaStatus{Hard: make(v1.ResourceList), Used: make(v1.ResourceList)}
for k, v := range resourceMap { for r := range supportedResources {
used, err := getUsage("", v) used, err := c.getUsage("", r)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var quantity resource.Quantity var quantity resource.Quantity
quantity.Set(int64(used)) quantity.Set(int64(used))
quota.Used[v1.ResourceName(k)] = quantity quota.Used[v1.ResourceName(r)] = quantity
} }
return &models.ResourceQuota{Namespace: "\"\"", Data: quota}, nil return &api.ResourceQuota{Namespace: "\"\"", Data: quota}, nil
} }
func GetNamespaceQuotas(namespace string) (*NamespacedResourceQuota, error) { func (c *resourceQuotaGetter) GetNamespaceQuota(namespace string) (*api.NamespacedResourceQuota, error) {
quota, err := getNamespaceResourceQuota(namespace) quota, err := c.getNamespaceResourceQuota(namespace)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
@@ -130,10 +127,10 @@ func GetNamespaceQuotas(namespace string) (*NamespacedResourceQuota, error) {
} }
// add extra quota usage, cause user may not specify them // add extra quota usage, cause user may not specify them
for key, val := range resourceMap { for key := range supportedResources {
// only add them when they don't exist in quotastatus // only add them when they don't exist in quotastatus
if _, ok := quota.Used[v1.ResourceName(key)]; !ok { if _, ok := quota.Used[v1.ResourceName(key)]; !ok {
used, err := getUsage(namespace, val) used, err := c.getUsage(namespace, key)
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)
return nil, err return nil, err
@@ -143,7 +140,7 @@ func GetNamespaceQuotas(namespace string) (*NamespacedResourceQuota, error) {
} }
} }
var result = NamespacedResourceQuota{ var result = api.NamespacedResourceQuota{
Namespace: namespace, Namespace: namespace,
} }
result.Data.Hard = quota.Hard result.Data.Hard = quota.Hard
@@ -169,8 +166,8 @@ func updateNamespaceQuota(tmpResourceList, resourceList v1.ResourceList) {
} }
} }
func getNamespaceResourceQuota(namespace string) (*v1.ResourceQuotaStatus, error) { func (c *resourceQuotaGetter) getNamespaceResourceQuota(namespace string) (*v1.ResourceQuotaStatus, error) {
resourceQuotaLister := informers.SharedInformerFactory().Core().V1().ResourceQuotas().Lister() resourceQuotaLister := c.informers.Core().V1().ResourceQuotas().Lister()
quotaList, err := resourceQuotaLister.ResourceQuotas(namespace).List(labels.Everything()) quotaList, err := resourceQuotaLister.ResourceQuotas(namespace).List(labels.Everything())
if err != nil { if err != nil {
klog.Error(err) klog.Error(err)

View File

@@ -5,26 +5,15 @@ import (
"time" "time"
) )
type AuthInfo struct {
Username string `json:"username" description:"username"`
Password string `json:"password" description:"password"`
ServerHost string `json:"serverhost" description:"registry server host"`
}
// ImageBlobInfo describes the info of an image. // ImageBlobInfo describes the info of an image.
type ImageDetails struct { type ImageDetails struct {
// Status is the status of the image search, such as "failed","succeeded". // Status is the status of the image search, such as "failed","succeeded".
Status string `json:"status,omitempty" description:"Status is the status of the image search, such as \"succeeded\"."` Status string `json:"status,omitempty" description:"Status is the status of the image search, such as \"succeeded\"."`
Message string `json:"message,omitempty" description:"Status message."`
Message string `json:"message,omitempty" description:"Status message."`
ImageManifest *ImageManifest `json:"imageManifest,omitempty" description:"Retrieve the manifest from the registry identified. Reference: https://docs.docker.com/registry/spec/api/#manifest"` ImageManifest *ImageManifest `json:"imageManifest,omitempty" description:"Retrieve the manifest from the registry identified. Reference: https://docs.docker.com/registry/spec/api/#manifest"`
ImageBlob *ImageBlob `json:"imageBlob,omitempty" description:"Retrieve the blob from the registry identified. Reference: https://docs.docker.com/registry/spec/api/#blob"`
ImageBlob *ImageBlob `json:"imageBlob,omitempty" description:"Retrieve the blob from the registry identified. Reference: https://docs.docker.com/registry/spec/api/#blob"` ImageTag string `json:"imageTag,omitempty" description:"image tag."`
Registry string `json:"registry,omitempty" description:"registry domain."`
ImageTag string `json:"imageTag,omitempty" description:"image tag."`
Registry string `json:"registry,omitempty" description:"registry domain."`
} }
type ImageBlob struct { type ImageBlob struct {

View File

@@ -24,10 +24,11 @@ import (
"fmt" "fmt"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/emicklei/go-restful"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/client-go/informers"
"k8s.io/klog" "k8s.io/klog"
log "k8s.io/klog" "kubesphere.io/kubesphere/pkg/api"
"kubesphere.io/kubesphere/pkg/informers"
) )
const ( const (
@@ -52,8 +53,21 @@ type DockerConfigEntry struct {
ServerAddress string `json:"serverAddress,omitempty"` ServerAddress string `json:"serverAddress,omitempty"`
} }
func RegistryVerify(authInfo AuthInfo) error { type RegistryGetter interface {
auth := base64.StdEncoding.EncodeToString([]byte(authInfo.Username + ":" + authInfo.Password)) VerifyRegistryCredential(credential api.RegistryCredential) error
GetEntry(namespace, secretName, imageName string) (ImageDetails, error)
}
type registryGetter struct {
informers informers.SharedInformerFactory
}
func NewRegistryGetter(informers informers.SharedInformerFactory) RegistryGetter {
return &registryGetter{informers: informers}
}
func (c *registryGetter) VerifyRegistryCredential(credential api.RegistryCredential) error {
auth := base64.StdEncoding.EncodeToString([]byte(credential.Username + ":" + credential.Password))
ctx := context.Background() ctx := context.Background()
cli, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation()) cli, err := client.NewClientWithOpts(client.WithAPIVersionNegotiation())
@@ -62,10 +76,10 @@ func RegistryVerify(authInfo AuthInfo) error {
} }
config := types.AuthConfig{ config := types.AuthConfig{
Username: authInfo.Username, Username: credential.Username,
Password: authInfo.Password, Password: credential.Password,
Auth: auth, Auth: auth,
ServerAddress: authInfo.ServerHost, ServerAddress: credential.ServerHost,
} }
resp, err := cli.RegistryLogin(ctx, config) resp, err := cli.RegistryLogin(ctx, config)
@@ -82,21 +96,77 @@ func RegistryVerify(authInfo AuthInfo) error {
} }
} }
func GetEntryBySecret(namespace, secretName string) (dockerConfigEntry *DockerConfigEntry, err error) { func (c *registryGetter) GetEntry(namespace, secretName, imageName string) (ImageDetails, error) {
if namespace == "" || secretName == "" { imageDetails, err := c.getEntryBySecret(namespace, secretName, imageName)
return &DockerConfigEntry{}, nil if imageDetails.Status == StatusFailed {
imageDetails.Message = err.Error()
} }
secret, err := informers.SharedInformerFactory().Core().V1().Secrets().Lister().Secrets(namespace).Get(secretName)
return imageDetails, err
}
func (c *registryGetter) getEntryBySecret(namespace, secretName, imageName string) (imageDetails ImageDetails, err error) {
failedImageDetails := ImageDetails{
Status: StatusFailed,
Message: "",
}
if namespace == "" || secretName == "" {
return failedImageDetails, fmt.Errorf("namespace or secret name not provided")
}
secret, err := c.informers.Core().V1().Secrets().Lister().Secrets(namespace).Get(secretName)
if err != nil { if err != nil {
log.Errorf("%+v", err) return failedImageDetails, err
return nil, err
} }
entry, err := getDockerEntryFromDockerSecret(secret) entry, err := getDockerEntryFromDockerSecret(secret)
if err != nil { if err != nil {
log.Errorf("%+v", err) return failedImageDetails, err
return nil, err
} }
return entry, nil
// parse image
image, err := ParseImage(imageName)
if err != nil {
return failedImageDetails, err
}
// Create the registry client.
r, err := CreateRegistryClient(entry.Username, entry.Password, image.Domain)
if err != nil {
return failedImageDetails, err
}
digestUrl := r.GetDigestUrl(image)
// Get token.
token, err := r.Token(digestUrl)
if err != nil {
return failedImageDetails, err
}
// Get digest.
imageManifest, err := r.ImageManifest(image, token)
if err != nil {
if serviceError, ok := err.(restful.ServiceError); ok {
return failedImageDetails, serviceError
}
return failedImageDetails, err
}
image.Digest = imageManifest.ManifestConfig.Digest
// Get blob.
imageBlob, err := r.ImageBlob(image, token)
if err != nil {
return failedImageDetails, err
}
return ImageDetails{
Status: StatusSuccess,
ImageManifest: imageManifest,
ImageBlob: imageBlob,
ImageTag: image.Tag,
Registry: image.Domain,
}, nil
} }
func getDockerEntryFromDockerSecret(instance *corev1.Secret) (dockerConfigEntry *DockerConfigEntry, err error) { func getDockerEntryFromDockerSecret(instance *corev1.Secret) (dockerConfigEntry *DockerConfigEntry, err error) {
@@ -117,9 +187,9 @@ func getDockerEntryFromDockerSecret(instance *corev1.Secret) (dockerConfigEntry
if len(dockerConfig.Auths) == 0 { if len(dockerConfig.Auths) == 0 {
return nil, fmt.Errorf("docker config auth len should not be 0") return nil, fmt.Errorf("docker config auth len should not be 0")
} }
for registryAddress, dockerConfigEntry := range dockerConfig.Auths { for registryAddress, dce := range dockerConfig.Auths {
dockerConfigEntry.ServerAddress = registryAddress dce.ServerAddress = registryAddress
return &dockerConfigEntry, nil return &dce, nil
} }
return nil, nil return nil, nil
} }

View File

@@ -1,167 +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 resources
import (
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort"
"strings"
"time"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/api/apps/v1"
)
type deploymentSearcher struct {
}
func (*deploymentSearcher) get(namespace, name string) (interface{}, error) {
return informers.SharedInformerFactory().Apps().V1().Deployments().Lister().Deployments(namespace).Get(name)
}
func deploymentStatus(item *v1.Deployment) string {
if item.Spec.Replicas != nil {
if item.Status.ReadyReplicas == 0 && *item.Spec.Replicas == 0 {
return StatusStopped
} else if item.Status.ReadyReplicas == *item.Spec.Replicas {
return StatusRunning
} else {
return StatusUpdating
}
}
return StatusStopped
}
// Exactly Match
func (*deploymentSearcher) match(match map[string]string, item *v1.Deployment) bool {
for k, v := range match {
switch k {
case Status:
if deploymentStatus(item) != v {
return false
}
case Name:
names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) {
return false
}
case Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) {
return false
}
default:
// label not exist or value not equal
if val, ok := item.Labels[k]; !ok || val != v {
return false
}
}
}
return true
}
func (*deploymentSearcher) fuzzy(fuzzy map[string]string, item *v1.Deployment) bool {
for k, v := range fuzzy {
switch k {
case Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false
}
case Label:
if !searchFuzzy(item.Labels, "", v) {
return false
}
case annotation:
if !searchFuzzy(item.Annotations, "", v) {
return false
}
return false
case app:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) {
return false
}
default:
if !searchFuzzy(item.Labels, k, v) {
return false
}
}
}
return true
}
func (s *deploymentSearcher) compare(a, b *v1.Deployment, orderBy string) bool {
switch orderBy {
case CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case UpdateTime:
return s.lastUpdateTime(a).Before(s.lastUpdateTime(b))
case Name:
fallthrough
default:
return strings.Compare(a.Name, b.Name) <= 0
}
}
func (s *deploymentSearcher) lastUpdateTime(deployment *v1.Deployment) time.Time {
lastUpdateTime := deployment.CreationTimestamp.Time
for _, condition := range deployment.Status.Conditions {
if condition.LastUpdateTime.After(lastUpdateTime) {
lastUpdateTime = condition.LastUpdateTime.Time
}
}
return lastUpdateTime
}
func (s *deploymentSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
deployments, err := informers.SharedInformerFactory().Apps().V1().Deployments().Lister().Deployments(namespace).List(labels.Everything())
if err != nil {
return nil, err
}
result := make([]*v1.Deployment, 0)
if len(conditions.Match) == 0 && len(conditions.Fuzzy) == 0 {
result = deployments
} else {
for _, item := range deployments {
if s.match(conditions.Match, item) && s.fuzzy(conditions.Fuzzy, item) {
result = append(result, item)
}
}
}
sort.Slice(result, func(i, j int) bool {
if reverse {
tmp := i
i = j
j = tmp
}
return s.compare(result[i], result[j], orderBy)
})
r := make([]interface{}, 0)
for _, i := range result {
r = append(r, i)
}
return r, nil
}

View File

@@ -1,120 +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 resources
import (
corev1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/informers"
"strconv"
)
type extraAnnotationInjector struct {
}
func (i extraAnnotationInjector) addExtraAnnotations(item interface{}) interface{} {
switch item.(type) {
case *corev1.PersistentVolumeClaim:
return i.injectPersistentVolumeClaim(item.(*corev1.PersistentVolumeClaim))
case *storagev1.StorageClass:
return i.injectStorageClass(item.(*storagev1.StorageClass))
}
return item
}
func (i extraAnnotationInjector) injectStorageClass(item *storagev1.StorageClass) *storagev1.StorageClass {
count, err := countPvcByStorageClass(item.Name)
if err != nil {
klog.Errorf("inject annotation failed %+v", err)
return item
}
item = item.DeepCopy()
if item.Annotations == nil {
item.Annotations = make(map[string]string, 0)
}
item.Annotations["kubesphere.io/pvc-count"] = strconv.Itoa(count)
return item
}
func (i extraAnnotationInjector) injectPersistentVolumeClaim(item *corev1.PersistentVolumeClaim) *corev1.PersistentVolumeClaim {
podLister := informers.SharedInformerFactory().Core().V1().Pods().Lister()
pods, err := podLister.Pods(item.Namespace).List(labels.Everything())
if err != nil {
klog.Errorf("inject annotation failed %+v", err)
return item
}
item = item.DeepCopy()
if item.Annotations == nil {
item.Annotations = make(map[string]string, 0)
}
if isPvcInUse(pods, item.Name) {
item.Annotations["kubesphere.io/in-use"] = "true"
} else {
item.Annotations["kubesphere.io/in-use"] = "false"
}
return item
}
func isPvcInUse(pods []*corev1.Pod, pvcName string) bool {
for _, pod := range pods {
volumes := pod.Spec.Volumes
for _, volume := range volumes {
pvc := volume.PersistentVolumeClaim
if pvc != nil && pvc.ClaimName == pvcName {
return true
}
}
}
return false
}
func countPvcByStorageClass(scName string) (int, error) {
persistentVolumeClaimLister := informers.SharedInformerFactory().Core().V1().PersistentVolumeClaims().Lister()
all, err := persistentVolumeClaimLister.List(labels.Everything())
if err != nil {
return 0, err
}
count := 0
for _, item := range all {
if item.Spec.StorageClassName != nil {
if *item.Spec.StorageClassName == scName {
count++
}
} else if item.GetAnnotations()[corev1.BetaStorageClassAnnotation] == scName {
count++
}
}
return count, nil
}

View File

@@ -1,186 +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 resources
import (
"fmt"
"k8s.io/klog"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
"strings"
)
func init() {
resources[ConfigMaps] = &configMapSearcher{}
resources[CronJobs] = &cronJobSearcher{}
resources[DaemonSets] = &daemonSetSearcher{}
resources[Deployments] = &deploymentSearcher{}
resources[Ingresses] = &ingressSearcher{}
resources[Jobs] = &jobSearcher{}
resources[PersistentVolumeClaims] = &persistentVolumeClaimSearcher{}
resources[Secrets] = &secretSearcher{}
resources[Services] = &serviceSearcher{}
resources[StatefulSets] = &statefulSetSearcher{}
resources[Pods] = &podSearcher{}
resources[Roles] = &roleSearcher{}
resources[S2iBuilders] = &s2iBuilderSearcher{}
resources[S2iRuns] = &s2iRunSearcher{}
resources[HorizontalPodAutoscalers] = &hpaSearcher{}
resources[Applications] = &appSearcher{}
resources[Nodes] = &nodeSearcher{}
resources[Namespaces] = &namespaceSearcher{}
resources[ClusterRoles] = &clusterRoleSearcher{}
resources[StorageClasses] = &storageClassesSearcher{}
resources[S2iBuilderTemplates] = &s2iBuilderTemplateSearcher{}
resources[Workspaces] = &workspaceSearcher{}
}
var (
injector = extraAnnotationInjector{}
resources = make(map[string]resourceSearchInterface)
clusterResources = []string{Nodes, Workspaces, Namespaces, ClusterRoles, StorageClasses, S2iBuilderTemplates}
)
const (
Name = "name"
Label = "label"
OwnerKind = "ownerKind"
OwnerName = "ownerName"
TargetKind = "targetKind"
TargetName = "targetName"
Role = "role"
CreateTime = "createTime"
UpdateTime = "updateTime"
StartTime = "startTime"
LastScheduleTime = "lastScheduleTime"
chart = "chart"
release = "release"
annotation = "annotation"
Keyword = "keyword"
UserFacing = "userfacing"
Status = "status"
includeCronJob = "includeCronJob"
storageClassName = "storageClassName"
cronJobKind = "CronJob"
s2iRunKind = "S2iRun"
includeS2iRun = "includeS2iRun"
StatusRunning = "running"
StatusPaused = "paused"
StatusPending = "pending"
StatusUpdating = "updating"
StatusStopped = "stopped"
StatusFailed = "failed"
StatusBound = "bound"
StatusLost = "lost"
StatusComplete = "complete"
StatusWarning = "warning"
StatusUnschedulable = "unschedulable"
app = "app"
Deployments = "deployments"
DaemonSets = "daemonsets"
Roles = "roles"
Workspaces = "workspaces"
WorkspaceRoles = "workspaceroles"
CronJobs = "cronjobs"
ConfigMaps = "configmaps"
Ingresses = "ingresses"
Jobs = "jobs"
PersistentVolumeClaims = "persistentvolumeclaims"
Pods = "pods"
Secrets = "secrets"
Services = "services"
StatefulSets = "statefulsets"
HorizontalPodAutoscalers = "horizontalpodautoscalers"
Applications = "applications"
Nodes = "nodes"
Namespaces = "namespaces"
StorageClasses = "storageclasses"
ClusterRoles = "clusterroles"
S2iBuilderTemplates = "s2ibuildertemplates"
S2iBuilders = "s2ibuilders"
S2iRuns = "s2iruns"
)
type resourceSearchInterface interface {
get(namespace, name string) (interface{}, error)
search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error)
}
func GetResource(namespace, resource, name string) (interface{}, error) {
if searcher, ok := resources[resource]; ok {
resource, err := searcher.get(namespace, name)
if err != nil {
klog.Errorf("resource %s.%s.%s not found: %s", namespace, resource, name, err)
return nil, err
}
return resource, nil
}
return nil, fmt.Errorf("resource %s.%s.%s not found", namespace, resource, name)
}
func ListResources(namespace, resource string, conditions *params.Conditions, orderBy string, reverse bool, limit, offset int) (*models.PageableResponse, error) {
items := make([]interface{}, 0)
var err error
var result []interface{}
// none namespace resource
if namespace != "" && sliceutil.HasString(clusterResources, resource) {
err = fmt.Errorf("namespaced resource %s not found", resource)
klog.Errorln(err)
return nil, err
}
if searcher, ok := resources[resource]; ok {
result, err = searcher.search(namespace, conditions, orderBy, reverse)
} else {
err = fmt.Errorf("namespaced resource %s not found", resource)
klog.Errorln(err)
return nil, err
}
if err != nil {
klog.Errorln(err)
return nil, err
}
if limit == -1 || limit+offset > len(result) {
limit = len(result) - offset
}
result = result[offset : offset+limit]
for _, item := range result {
items = append(items, injector.addExtraAnnotations(item))
}
return &models.PageableResponse{TotalCount: len(result), Items: items}, nil
}
func searchFuzzy(m map[string]string, key, value string) bool {
val, exist := m[key]
if value == "" && (!exist || val == "") {
return true
} else if value != "" && strings.Contains(val, value) {
return true
}
return false
}

View File

@@ -16,37 +16,49 @@
* / * /
*/ */
package resources package application
import ( import (
"github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1" "github.com/kubernetes-sigs/application/pkg/apis/app/v1beta1"
"github.com/kubernetes-sigs/application/pkg/client/informers/externalversions"
"k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
"strings" "strings"
) )
const (
app = "app"
chart = "chart"
release = "release"
)
type appSearcher struct { type appSearcher struct {
informer externalversions.SharedInformerFactory
} }
func (*appSearcher) get(namespace, name string) (interface{}, error) { func NewApplicationSearcher(informers externalversions.SharedInformerFactory) v1alpha2.Interface {
return informers.AppSharedInformerFactory().App().V1beta1().Applications().Lister().Applications(namespace).Get(name) return &appSearcher{informer: informers}
}
func (s *appSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.App().V1beta1().Applications().Lister().Applications(namespace).Get(name)
} }
// exactly Match // exactly Match
func (*appSearcher) match(match map[string]string, item *v1beta1.Application) bool { func (s *appSearcher) match(match map[string]string, item *v1beta1.Application) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case Name: case v1alpha2.Name:
names := strings.Split(v, "|") names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) { if !sliceutil.HasString(names, item.Name) {
return false return false
} }
case Keyword: case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false return false
} }
default: default:
@@ -63,16 +75,16 @@ func (*appSearcher) match(match map[string]string, item *v1beta1.Application) bo
func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool { func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { switch k {
case Name: case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false return false
} }
case Label: case v1alpha2.Label:
if !searchFuzzy(item.Labels, "", v) { if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false return false
} }
case annotation: case v1alpha2.Annotation:
if !searchFuzzy(item.Annotations, "", v) { if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false return false
} }
return false return false
@@ -81,7 +93,7 @@ func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bo
return false return false
} }
default: default:
if !searchFuzzy(item.Labels, k, v) { if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false return false
} }
} }
@@ -91,17 +103,17 @@ func (*appSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.Application) bo
func (*appSearcher) compare(a, b *v1beta1.Application, orderBy string) bool { func (*appSearcher) compare(a, b *v1beta1.Application, orderBy string) bool {
switch orderBy { switch orderBy {
case CreateTime: case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name: case v1alpha2.Name:
fallthrough fallthrough
default: default:
return strings.Compare(a.Name, b.Name) <= 0 return strings.Compare(a.Name, b.Name) <= 0
} }
} }
func (s *appSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *appSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
apps, err := informers.AppSharedInformerFactory().App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything()) apps, err := s.informer.App().V1beta1().Applications().Lister().Applications(namespace).List(labels.Everything())
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -15,11 +15,12 @@
limitations under the License. limitations under the License.
*/ */
package resources package clusterrole
import ( import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/k8sutil" "kubesphere.io/kubesphere/pkg/utils/k8sutil"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
@@ -31,34 +32,39 @@ import (
) )
type clusterRoleSearcher struct { type clusterRoleSearcher struct {
informer informers.SharedInformerFactory
} }
func (*clusterRoleSearcher) get(namespace, name string) (interface{}, error) { func NewClusterRoleSearcher(informer informers.SharedInformerFactory) v1alpha2.Interface {
return informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister().Get(name) return &clusterRoleSearcher{informer: informer}
}
func (s *clusterRoleSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Rbac().V1().ClusterRoles().Lister().Get(name)
} }
// exactly Match // exactly Match
func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool { func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRole) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case OwnerKind: case v1alpha2.OwnerKind:
fallthrough fallthrough
case OwnerName: case v1alpha2.OwnerName:
kind := match[OwnerKind] kind := match[v1alpha2.OwnerKind]
name := match[OwnerName] name := match[v1alpha2.OwnerName]
if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) { if !k8sutil.IsControlledBy(item.OwnerReferences, kind, name) {
return false return false
} }
case Name: case v1alpha2.Name:
names := strings.Split(v, "|") names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) { if !sliceutil.HasString(names, item.Name) {
return false return false
} }
case Keyword: case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false return false
} }
case UserFacing: case v1alpha2.UserFacing:
if v == "true" { if v == "true" {
if !isUserFacingClusterRole(item) { if !isUserFacingClusterRole(item) {
return false return false
@@ -78,21 +84,21 @@ func (*clusterRoleSearcher) match(match map[string]string, item *rbac.ClusterRol
func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool { func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRole) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { switch k {
case Name: case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false return false
} }
case Label: case v1alpha2.Label:
if !searchFuzzy(item.Labels, "", v) { if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false return false
} }
case annotation: case v1alpha2.Annotation:
if !searchFuzzy(item.Annotations, "", v) { if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false return false
} }
return false return false
default: default:
if !searchFuzzy(item.Labels, k, v) { if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false return false
} }
} }
@@ -102,17 +108,17 @@ func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRol
func (*clusterRoleSearcher) compare(a, b *rbac.ClusterRole, orderBy string) bool { func (*clusterRoleSearcher) compare(a, b *rbac.ClusterRole, orderBy string) bool {
switch orderBy { switch orderBy {
case CreateTime: case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name: case v1alpha2.Name:
fallthrough fallthrough
default: default:
return strings.Compare(a.Name, b.Name) <= 0 return strings.Compare(a.Name, b.Name) <= 0
} }
} }
func (s *clusterRoleSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *clusterRoleSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
clusterRoles, err := informers.SharedInformerFactory().Rbac().V1().ClusterRoles().Lister().List(labels.Everything()) clusterRoles, err := s.informer.Rbac().V1().ClusterRoles().Lister().List(labels.Everything())
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -15,11 +15,12 @@
limitations under the License. limitations under the License.
*/ */
package resources package configmap
import ( import (
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/constants" "kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/models/resources/v1alpha2"
"kubesphere.io/kubesphere/pkg/server/params" "kubesphere.io/kubesphere/pkg/server/params"
"kubesphere.io/kubesphere/pkg/utils/sliceutil" "kubesphere.io/kubesphere/pkg/utils/sliceutil"
"sort" "sort"
@@ -30,23 +31,28 @@ import (
) )
type configMapSearcher struct { type configMapSearcher struct {
informer informers.SharedInformerFactory
} }
func (*configMapSearcher) get(namespace, name string) (interface{}, error) { func NewConfigmapSearcher(informers informers.SharedInformerFactory) v1alpha2.Interface {
return informers.SharedInformerFactory().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name) return &configMapSearcher{informer: informers}
}
func (s *configMapSearcher) Get(namespace, name string) (interface{}, error) {
return s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).Get(name)
} }
// exactly Match // exactly Match
func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool { func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) bool {
for k, v := range match { for k, v := range match {
switch k { switch k {
case Name: case v1alpha2.Name:
names := strings.Split(v, "|") names := strings.Split(v, "|")
if !sliceutil.HasString(names, item.Name) { if !sliceutil.HasString(names, item.Name) {
return false return false
} }
case Keyword: case v1alpha2.Keyword:
if !strings.Contains(item.Name, v) && !searchFuzzy(item.Labels, "", v) && !searchFuzzy(item.Annotations, "", v) { if !strings.Contains(item.Name, v) && !v1alpha2.SearchFuzzy(item.Labels, "", v) && !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false return false
} }
default: default:
@@ -63,25 +69,25 @@ func (*configMapSearcher) match(match map[string]string, item *v1.ConfigMap) boo
func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool { func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) bool {
for k, v := range fuzzy { for k, v := range fuzzy {
switch k { switch k {
case Name: case v1alpha2.Name:
if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) { if !strings.Contains(item.Name, v) && !strings.Contains(item.Annotations[constants.DisplayNameAnnotationKey], v) {
return false return false
} }
case Label: case v1alpha2.Label:
if !searchFuzzy(item.Labels, "", v) { if !v1alpha2.SearchFuzzy(item.Labels, "", v) {
return false return false
} }
case annotation: case v1alpha2.Annotation:
if !searchFuzzy(item.Annotations, "", v) { if !v1alpha2.SearchFuzzy(item.Annotations, "", v) {
return false return false
} }
return false return false
case app: case v1alpha2.App:
if !strings.Contains(item.Labels[chart], v) && !strings.Contains(item.Labels[release], v) { if !strings.Contains(item.Labels[v1alpha2.Chart], v) && !strings.Contains(item.Labels[v1alpha2.Release], v) {
return false return false
} }
default: default:
if !searchFuzzy(item.Labels, k, v) { if !v1alpha2.SearchFuzzy(item.Labels, k, v) {
return false return false
} }
} }
@@ -91,17 +97,17 @@ func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) boo
func (*configMapSearcher) compare(a, b *v1.ConfigMap, orderBy string) bool { func (*configMapSearcher) compare(a, b *v1.ConfigMap, orderBy string) bool {
switch orderBy { switch orderBy {
case CreateTime: case v1alpha2.CreateTime:
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time) return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case Name: case v1alpha2.Name:
fallthrough fallthrough
default: default:
return strings.Compare(a.Name, b.Name) <= 0 return strings.Compare(a.Name, b.Name) <= 0
} }
} }
func (s *configMapSearcher) search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) { func (s *configMapSearcher) Search(namespace string, conditions *params.Conditions, orderBy string, reverse bool) ([]interface{}, error) {
configMaps, err := informers.SharedInformerFactory().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything()) configMaps, err := s.informer.Core().V1().ConfigMaps().Lister().ConfigMaps(namespace).List(labels.Everything())
if err != nil { if err != nil {
return nil, err return nil, err
@@ -120,9 +126,7 @@ func (s *configMapSearcher) search(namespace string, conditions *params.Conditio
} }
sort.Slice(result, func(i, j int) bool { sort.Slice(result, func(i, j int) bool {
if reverse { if reverse {
tmp := i i, j = j, i
i = j
j = tmp
} }
return s.compare(result[i], result[j], orderBy) return s.compare(result[i], result[j], orderBy)
}) })

Some files were not shown because too many files have changed in this diff Show More