mirror of
https://github.com/niusmallnan/steve.git
synced 2025-06-24 13:41:35 +00:00
Add fields to cluster
This commit is contained in:
parent
0849182bdd
commit
2eb87bffc1
@ -3,14 +3,21 @@ package clusters
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/rancher/steve/pkg/clustercache"
|
||||
"github.com/rancher/steve/pkg/schemaserver/store/empty"
|
||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||
"github.com/rancher/steve/pkg/server/store/proxy"
|
||||
"github.com/rancher/steve/pkg/server/store/switchschema"
|
||||
"github.com/rancher/steve/pkg/server/store/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 (
|
||||
@ -31,15 +38,22 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
type Cluster struct {
|
||||
}
|
||||
func Register(ctx context.Context, schemas *types.APISchemas, cg proxy.ClientGetter, cluster clustercache.ClusterCache) error {
|
||||
k8s, err := cg.AdminK8sInterface()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
func Register(ctx context.Context, schemas *types.APISchemas, cg proxy.ClientGetter, cluster clustercache.ClusterCache) {
|
||||
shell := &shell{
|
||||
cg: cg,
|
||||
namespace: "dashboard-shells",
|
||||
}
|
||||
|
||||
picker := &picker{
|
||||
start: time.Now(),
|
||||
discovery: k8s.Discovery(),
|
||||
}
|
||||
|
||||
cluster.OnAdd(ctx, shell.PurgeOldShell)
|
||||
cluster.OnChange(ctx, func(gvr schema.GroupVersionResource, key string, obj, oldObj runtime.Object) error {
|
||||
return shell.PurgeOldShell(gvr, key, obj)
|
||||
@ -47,74 +61,112 @@ func Register(ctx context.Context, schemas *types.APISchemas, cg proxy.ClientGet
|
||||
schemas.MustImportAndCustomize(Cluster{}, func(schema *types.APISchema) {
|
||||
schema.CollectionMethods = []string{http.MethodGet}
|
||||
schema.ResourceMethods = []string{http.MethodGet}
|
||||
schema.Store = &Store{}
|
||||
|
||||
schema.Formatter = Format
|
||||
schema.Store = &switchstore.Store{
|
||||
Picker: picker.Picker,
|
||||
}
|
||||
schema.LinkHandlers = map[string]http.Handler{
|
||||
"shell": shell,
|
||||
}
|
||||
|
||||
schema.Formatter = func(request *types.APIRequest, resource *types.RawResource) {
|
||||
resource.Links["api"] = request.URLBuilder.RelativeToRoot("/k8s/clusters/" + resource.ID)
|
||||
}
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func toClusterList(obj types.APIObjectList, err error) (types.APIObjectList, error) {
|
||||
for i := range obj.Objects {
|
||||
obj.Objects[i], _ = toCluster(obj.Objects[i], err)
|
||||
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 obj, err
|
||||
}
|
||||
|
||||
func toCluster(obj types.APIObject, err error) (types.APIObject, error) {
|
||||
return types.APIObject{
|
||||
Type: "cluster",
|
||||
ID: obj.ID,
|
||||
Object: &Cluster{},
|
||||
}, err
|
||||
return &switchschema.Store{
|
||||
Schema: clusters,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Store) ByID(apiOp *types.APIRequest, schema *types.APISchema, id string) (types.APIObject, error) {
|
||||
clusters := apiOp.Schemas.LookupSchema(rancherCluster)
|
||||
if clusters == nil {
|
||||
if id == localID {
|
||||
return local, nil
|
||||
}
|
||||
return types.APIObject{}, validation.NotFound
|
||||
if id == localID {
|
||||
return s.newLocal(), nil
|
||||
}
|
||||
return toCluster(clusters.Store.ByID(apiOp, clusters, id))
|
||||
return types.APIObject{}, validation.NotFound
|
||||
}
|
||||
|
||||
func (s *Store) List(apiOp *types.APIRequest, schema *types.APISchema) (types.APIObjectList, error) {
|
||||
clusters := apiOp.Schemas.LookupSchema(rancherCluster)
|
||||
if clusters == nil {
|
||||
return localList, nil
|
||||
}
|
||||
return toClusterList(clusters.Store.List(apiOp, clusters))
|
||||
return types.APIObjectList{
|
||||
Objects: []types.APIObject{
|
||||
s.newLocal(),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Store) Watch(apiOp *types.APIRequest, schema *types.APISchema, w types.WatchRequest) (chan types.APIEvent, error) {
|
||||
clusters := apiOp.Schemas.LookupSchema(rancherCluster)
|
||||
if clusters == nil {
|
||||
return nil, 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",
|
||||
},
|
||||
}
|
||||
target, err := clusters.Store.Watch(apiOp, clusters, w)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
version, err := s.discovery.ServerVersion()
|
||||
if err == nil {
|
||||
cluster.Status.Version = version
|
||||
}
|
||||
return types.APIObject{
|
||||
Type: "cluster",
|
||||
ID: localID,
|
||||
Object: cluster,
|
||||
}
|
||||
|
||||
result := make(chan types.APIEvent)
|
||||
go func() {
|
||||
defer close(result)
|
||||
for event := range target {
|
||||
event.Object, _ = toCluster(event.Object, nil)
|
||||
result <- event
|
||||
}
|
||||
}()
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
@ -20,14 +20,15 @@ import (
|
||||
"k8s.io/client-go/discovery"
|
||||
)
|
||||
|
||||
func DefaultSchemas(ctx context.Context, baseSchema *types.APISchemas, ccache clustercache.ClusterCache, cg proxy.ClientGetter) *types.APISchemas {
|
||||
func DefaultSchemas(ctx context.Context, baseSchema *types.APISchemas, ccache clustercache.ClusterCache, cg proxy.ClientGetter) (*types.APISchemas, error) {
|
||||
counts.Register(baseSchema, ccache)
|
||||
subscribe.Register(baseSchema)
|
||||
apiroot.Register(baseSchema, []string{"v1"}, []string{"proxy:/apis"})
|
||||
userpreferences.Register(baseSchema, cg)
|
||||
clusters.Register(ctx, baseSchema, cg, ccache)
|
||||
helm.Register(baseSchema)
|
||||
return baseSchema
|
||||
|
||||
err := clusters.Register(ctx, baseSchema, cg, ccache)
|
||||
return baseSchema, err
|
||||
}
|
||||
|
||||
func DefaultSchemaTemplates(cf *client.Factory, lookup accesscontrol.AccessSetLookup, discovery discovery.DiscoveryInterface) []schema.Template {
|
||||
|
@ -67,7 +67,11 @@ func setup(ctx context.Context, server *Server) (http.Handler, *schema.Collectio
|
||||
|
||||
ccache := clustercache.NewClusterCache(ctx, cf.DynamicClient())
|
||||
|
||||
server.BaseSchemas = resources.DefaultSchemas(ctx, server.BaseSchemas, ccache, cf)
|
||||
server.BaseSchemas, err = resources.DefaultSchemas(ctx, server.BaseSchemas, ccache, cf)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
server.SchemaTemplates = append(server.SchemaTemplates, resources.DefaultSchemaTemplates(cf, asl, server.K8s.Discovery())...)
|
||||
|
||||
cols, err := common.NewDynamicColumns(server.RestConfig)
|
||||
|
59
pkg/server/store/switchstore/store.go
Normal file
59
pkg/server/store/switchstore/store.go
Normal file
@ -0,0 +1,59 @@
|
||||
package switchstore
|
||||
|
||||
import (
|
||||
"github.com/rancher/steve/pkg/schemaserver/types"
|
||||
)
|
||||
|
||||
type StorePicker func(apiOp *types.APIRequest, schema *types.APISchema, verb, id string) (types.Store, error)
|
||||
|
||||
type Store struct {
|
||||
Picker StorePicker
|
||||
}
|
||||
|
||||
func (e *Store) Delete(apiOp *types.APIRequest, schema *types.APISchema, id string) (types.APIObject, error) {
|
||||
s, err := e.Picker(apiOp, schema, "delete", id)
|
||||
if err != nil {
|
||||
return types.APIObject{}, err
|
||||
}
|
||||
return s.Delete(apiOp, schema, id)
|
||||
}
|
||||
|
||||
func (e *Store) ByID(apiOp *types.APIRequest, schema *types.APISchema, id string) (types.APIObject, error) {
|
||||
s, err := e.Picker(apiOp, schema, "get", id)
|
||||
if err != nil {
|
||||
return types.APIObject{}, err
|
||||
}
|
||||
return s.ByID(apiOp, schema, id)
|
||||
}
|
||||
|
||||
func (e *Store) List(apiOp *types.APIRequest, schema *types.APISchema) (types.APIObjectList, error) {
|
||||
s, err := e.Picker(apiOp, schema, "list", "")
|
||||
if err != nil {
|
||||
return types.APIObjectList{}, err
|
||||
}
|
||||
return s.List(apiOp, schema)
|
||||
}
|
||||
|
||||
func (e *Store) Create(apiOp *types.APIRequest, schema *types.APISchema, data types.APIObject) (types.APIObject, error) {
|
||||
s, err := e.Picker(apiOp, schema, "create", "")
|
||||
if err != nil {
|
||||
return types.APIObject{}, err
|
||||
}
|
||||
return s.Create(apiOp, schema, data)
|
||||
}
|
||||
|
||||
func (e *Store) Update(apiOp *types.APIRequest, schema *types.APISchema, data types.APIObject, id string) (types.APIObject, error) {
|
||||
s, err := e.Picker(apiOp, schema, "update", id)
|
||||
if err != nil {
|
||||
return types.APIObject{}, err
|
||||
}
|
||||
return s.Update(apiOp, schema, data, id)
|
||||
}
|
||||
|
||||
func (e *Store) Watch(apiOp *types.APIRequest, schema *types.APISchema, wr types.WatchRequest) (chan types.APIEvent, error) {
|
||||
s, err := e.Picker(apiOp, schema, "watch", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s.Watch(apiOp, schema, wr)
|
||||
}
|
Loading…
Reference in New Issue
Block a user