devlopment branch (#1736)
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
17
go.mod
@@ -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
27
go.sum
@@ -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=
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
1
pkg/api/resource/resource.go
Normal file
1
pkg/api/resource/resource.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package resource
|
||||||
29
pkg/api/resource/v1alpha2/types.go
Normal file
29
pkg/api/resource/v1alpha2/types.go
Normal 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
170
pkg/api/types.go
Normal 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) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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")
|
||||||
|
|||||||
@@ -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()
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
8
pkg/apis/addtoscheme_logging_v1alpha2.go
Normal file
8
pkg/apis/addtoscheme_logging_v1alpha2.go
Normal 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)
|
||||||
|
}
|
||||||
@@ -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))
|
||||||
|
|||||||
1
pkg/apis/logging/group.go
Normal file
1
pkg/apis/logging/group.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package logging
|
||||||
23
pkg/apis/logging/v1alpha2/doc.go
Normal file
23
pkg/apis/logging/v1alpha2/doc.go
Normal 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
|
||||||
71
pkg/apis/logging/v1alpha2/fluentbit_types.go
Normal file
71
pkg/apis/logging/v1alpha2/fluentbit_types.go
Normal 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"`
|
||||||
|
}
|
||||||
44
pkg/apis/logging/v1alpha2/register.go
Normal file
44
pkg/apis/logging/v1alpha2/register.go
Normal 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()
|
||||||
|
}
|
||||||
251
pkg/apis/logging/v1alpha2/zz_generated.deepcopy.go
generated
Normal file
251
pkg/apis/logging/v1alpha2/zz_generated.deepcopy.go
generated
Normal 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
|
||||||
|
}
|
||||||
@@ -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))
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
81
pkg/apiserver/apiserver.go
Normal file
81
pkg/apiserver/apiserver.go
Normal 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")
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
30
pkg/apiserver/query/field.go
Normal file
30
pkg/apiserver/query/field.go
Normal 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,
|
||||||
|
}
|
||||||
145
pkg/apiserver/query/types.go
Normal file
145
pkg/apiserver/query/types.go
Normal 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
|
||||||
|
}
|
||||||
72
pkg/apiserver/query/types_test.go
Normal file
72
pkg/apiserver/query/types_test.go
Normal 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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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(®istries.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(®istries.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(®istries.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(®istries.ImageDetails{Status: registries.StatusFailed, Message: serviceError.Message})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Errorf("%+v", err)
|
|
||||||
response.WriteAsJson(®istries.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(®istries.ImageDetails{Status: registries.StatusFailed, Message: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
imageDetails := ®istries.ImageDetails{
|
|
||||||
Status: registries.StatusSuccess,
|
|
||||||
ImageManifest: imageManifest,
|
|
||||||
ImageBlob: imageBlob,
|
|
||||||
ImageTag: image.Tag,
|
|
||||||
Registry: image.Domain,
|
|
||||||
}
|
|
||||||
|
|
||||||
response.WriteAsJson(imageDetails)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
20
pkg/client/clientset/versioned/typed/logging/v1alpha2/doc.go
Normal file
20
pkg/client/clientset/versioned/typed/logging/v1alpha2/doc.go
Normal 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
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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{}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
46
pkg/client/informers/externalversions/logging/interface.go
Normal file
46
pkg/client/informers/externalversions/logging/interface.go
Normal 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)
|
||||||
|
}
|
||||||
@@ -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())
|
||||||
|
}
|
||||||
@@ -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}
|
||||||
|
}
|
||||||
27
pkg/client/listers/logging/v1alpha2/expansion_generated.go
Normal file
27
pkg/client/listers/logging/v1alpha2/expansion_generated.go
Normal 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{}
|
||||||
94
pkg/client/listers/logging/v1alpha2/fluentbit.go
Normal file
94
pkg/client/listers/logging/v1alpha2/fluentbit.go
Normal 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
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
14
pkg/kapis/openpitrix/v1/handler.go
Normal file
14
pkg/kapis/openpitrix/v1/handler.go
Normal 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) {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
48
pkg/kapis/operations/v1alpha2/handler.go
Normal file
48
pkg/kapis/operations/v1alpha2/handler.go
Normal 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)
|
||||||
|
}
|
||||||
@@ -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")).
|
||||||
|
|||||||
@@ -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))
|
|
||||||
}
|
|
||||||
345
pkg/kapis/resources/v1alpha2/handler.go
Normal file
345
pkg/kapis/resources/v1alpha2/handler.go
Normal 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, ¶ms.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)
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|
||||||
|
|||||||
91
pkg/kapis/resources/v1alpha3/handler.go
Normal file
91
pkg/kapis/resources/v1alpha3/handler.go
Normal 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)
|
||||||
|
}
|
||||||
7
pkg/kapis/resources/v1alpha3/handler_test.go
Normal file
7
pkg/kapis/resources/v1alpha3/handler_test.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package v1alpha3
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestComponentHandler(t *testing.T) {
|
||||||
|
|
||||||
|
}
|
||||||
81
pkg/kapis/resources/v1alpha3/register.go
Normal file
81
pkg/kapis/resources/v1alpha3/register.go
Normal 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
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
356
pkg/models/components/components_test.go
Normal file
356
pkg/models/components/components_test.go
Normal 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
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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"`
|
||||||
|
|||||||
@@ -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
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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", ¶ms.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)
|
||||||
|
|||||||
@@ -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, ¶ms.Conditions{}, "", false, 1, 0)
|
|
||||||
} else {
|
|
||||||
result, err = resources.ListResources(namespace, resource, ¶ms.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)
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 ®istryGetter{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
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -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
Reference in New Issue
Block a user