mirror of
https://github.com/rancher/steve.git
synced 2025-06-27 07:17:13 +00:00
175 lines
4.0 KiB
Go
175 lines
4.0 KiB
Go
package clusters
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/rancher/apiserver/pkg/store/empty"
|
|
"github.com/rancher/apiserver/pkg/types"
|
|
"github.com/rancher/steve/pkg/clustercache"
|
|
"github.com/rancher/steve/pkg/podimpersonation"
|
|
"github.com/rancher/steve/pkg/stores/proxy"
|
|
"github.com/rancher/steve/pkg/stores/switchschema"
|
|
"github.com/rancher/steve/pkg/stores/switchstore"
|
|
"github.com/rancher/wrangler/pkg/data"
|
|
"github.com/rancher/wrangler/pkg/schemas/validation"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
"k8s.io/apimachinery/pkg/version"
|
|
"k8s.io/client-go/discovery"
|
|
)
|
|
|
|
const (
|
|
rancherCluster = "management.cattle.io.cluster"
|
|
localID = "local"
|
|
)
|
|
|
|
var (
|
|
local = types.APIObject{
|
|
Type: "cluster",
|
|
ID: localID,
|
|
Object: &Cluster{},
|
|
}
|
|
localList = types.APIObjectList{
|
|
Objects: []types.APIObject{
|
|
local,
|
|
},
|
|
}
|
|
)
|
|
|
|
func Register(ctx context.Context, schemas *types.APISchemas, cg proxy.ClientGetter, cluster clustercache.ClusterCache) error {
|
|
k8s, err := cg.AdminK8sInterface()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
shell := &shell{
|
|
cg: cg,
|
|
namespace: "dashboard-shells",
|
|
impersonator: podimpersonation.New("shell", cg, time.Hour),
|
|
}
|
|
|
|
picker := &picker{
|
|
start: time.Now(),
|
|
discovery: k8s.Discovery(),
|
|
}
|
|
|
|
cluster.OnAdd(ctx, shell.impersonator.PurgeOldRoles)
|
|
cluster.OnChange(ctx, func(gvr schema.GroupVersionResource, key string, obj, oldObj runtime.Object) error {
|
|
return shell.impersonator.PurgeOldRoles(gvr, key, obj)
|
|
})
|
|
schemas.MustImportAndCustomize(Cluster{}, func(schema *types.APISchema) {
|
|
schema.CollectionMethods = []string{http.MethodGet}
|
|
schema.ResourceMethods = []string{http.MethodGet}
|
|
schema.Formatter = Format
|
|
schema.Store = &switchstore.Store{
|
|
Picker: picker.Picker,
|
|
}
|
|
schema.LinkHandlers = map[string]http.Handler{
|
|
"shell": shell,
|
|
}
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
type Cluster struct {
|
|
metav1.ObjectMeta `json:"metadata,omitempty"`
|
|
|
|
Spec ClusterSpec `json:"spec"`
|
|
Status ClusterStatus `json:"status"`
|
|
}
|
|
|
|
type ClusterSpec struct {
|
|
DisplayName string `json:"displayName"`
|
|
}
|
|
|
|
type ClusterStatus struct {
|
|
Driver string `json:"driver"`
|
|
Version *version.Info `json:"version,omitempty"`
|
|
}
|
|
|
|
func Format(request *types.APIRequest, resource *types.RawResource) {
|
|
copy := [][]string{
|
|
{"spec", "displayName"},
|
|
{"metadata", "creationTimestamp"},
|
|
{"status", "driver"},
|
|
{"status", "version"},
|
|
}
|
|
|
|
from := resource.APIObject.Data()
|
|
to := data.New()
|
|
|
|
for _, keys := range copy {
|
|
to.SetNested(data.GetValueN(from, keys...), keys...)
|
|
}
|
|
|
|
resource.APIObject.Object = to
|
|
resource.Links["api"] = request.URLBuilder.RelativeToRoot("/k8s/clusters/" + resource.ID)
|
|
}
|
|
|
|
type Store struct {
|
|
empty.Store
|
|
|
|
start time.Time
|
|
discovery discovery.DiscoveryInterface
|
|
}
|
|
|
|
type picker struct {
|
|
start time.Time
|
|
discovery discovery.DiscoveryInterface
|
|
}
|
|
|
|
func (p *picker) Picker(apiOp *types.APIRequest, schema *types.APISchema, verb, id string) (types.Store, error) {
|
|
clusters := apiOp.Schemas.LookupSchema(rancherCluster)
|
|
if clusters == nil {
|
|
return &Store{
|
|
start: p.start,
|
|
discovery: p.discovery,
|
|
}, nil
|
|
}
|
|
return &switchschema.Store{
|
|
Schema: clusters,
|
|
}, nil
|
|
}
|
|
|
|
func (s *Store) ByID(apiOp *types.APIRequest, schema *types.APISchema, id string) (types.APIObject, error) {
|
|
if id == localID {
|
|
return s.newLocal(), nil
|
|
}
|
|
return types.APIObject{}, validation.NotFound
|
|
}
|
|
|
|
func (s *Store) List(apiOp *types.APIRequest, schema *types.APISchema) (types.APIObjectList, error) {
|
|
return types.APIObjectList{
|
|
Objects: []types.APIObject{
|
|
s.newLocal(),
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (s *Store) newLocal() types.APIObject {
|
|
cluster := &Cluster{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
CreationTimestamp: metav1.NewTime(s.start),
|
|
},
|
|
Spec: ClusterSpec{
|
|
DisplayName: "Remote",
|
|
},
|
|
Status: ClusterStatus{
|
|
Driver: "remote",
|
|
},
|
|
}
|
|
version, err := s.discovery.ServerVersion()
|
|
if err == nil {
|
|
cluster.Status.Version = version
|
|
}
|
|
return types.APIObject{
|
|
Type: "cluster",
|
|
ID: localID,
|
|
Object: cluster,
|
|
}
|
|
}
|