Skip to content

Commit aa8a623

Browse files
committed
apiserver: add enable subresource options
Signed-off-by: Iceber Gu <[email protected]>
1 parent 80faec0 commit aa8a623

File tree

4 files changed

+118
-19
lines changed

4 files changed

+118
-19
lines changed

cmd/apiserver/app/options/options.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
"github.com/clusterpedia-io/clusterpedia/pkg/apiserver"
2323
generatedopenapi "github.com/clusterpedia-io/clusterpedia/pkg/generated/openapi"
24+
"github.com/clusterpedia-io/clusterpedia/pkg/kubeapiserver"
2425
"github.com/clusterpedia-io/clusterpedia/pkg/storage"
2526
storageoptions "github.com/clusterpedia-io/clusterpedia/pkg/storage/options"
2627
)
@@ -40,7 +41,8 @@ type ClusterPediaServerOptions struct {
4041
Traces *genericoptions.TracingOptions
4142
Metrics *metrics.Options
4243

43-
Storage *storageoptions.StorageOptions
44+
Storage *storageoptions.StorageOptions
45+
ResourceServer *kubeapiserver.Options
4446
}
4547

4648
func NewServerOptions() *ClusterPediaServerOptions {
@@ -70,7 +72,8 @@ func NewServerOptions() *ClusterPediaServerOptions {
7072
Traces: genericoptions.NewTracingOptions(),
7173
Metrics: metrics.NewOptions(),
7274

73-
Storage: storageoptions.NewStorageOptions(),
75+
Storage: storageoptions.NewStorageOptions(),
76+
ResourceServer: kubeapiserver.NewOptions(),
7477
}
7578
}
7679

@@ -94,6 +97,11 @@ func (o *ClusterPediaServerOptions) Config() (*apiserver.Config, error) {
9497
return nil, err
9598
}
9699

100+
resourceServerConfig, err := o.ResourceServer.Config()
101+
if err != nil {
102+
return nil, err
103+
}
104+
97105
if err := o.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil {
98106
return nil, fmt.Errorf("error create self-signed certificates: %v", err)
99107
}
@@ -121,6 +129,7 @@ func (o *ClusterPediaServerOptions) Config() (*apiserver.Config, error) {
121129
return &apiserver.Config{
122130
GenericConfig: genericConfig,
123131
StorageFactory: storage,
132+
ExtraConfig: resourceServerConfig,
124133
}, nil
125134
}
126135

@@ -178,6 +187,7 @@ func (o *ClusterPediaServerOptions) Flags() cliflag.NamedFlagSets {
178187
o.Metrics.AddFlags(fss.FlagSet("metrics"))
179188

180189
o.Storage.AddFlags(fss.FlagSet("storage"))
190+
o.ResourceServer.AddFlags(fss.FlagSet("resource server"))
181191
return fss
182192
}
183193

pkg/apiserver/apiserver.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ type Config struct {
6464
GenericConfig *genericapiserver.RecommendedConfig
6565

6666
StorageFactory storage.StorageFactory
67+
ExtraConfig *kubeapiserver.ExtraConfig
6768
}
6869

6970
type ClusterPediaServer struct {
@@ -75,6 +76,7 @@ type completedConfig struct {
7576

7677
ClientConfig *clientrest.Config
7778
StorageFactory storage.StorageFactory
79+
ExtraConfig *kubeapiserver.ExtraConfig
7880
}
7981

8082
// CompletedConfig embeds a private pointer that cannot be instantiated outside of this package.
@@ -90,6 +92,7 @@ func (cfg *Config) Complete() CompletedConfig {
9092
cfg.GenericConfig.Complete(),
9193
cfg.GenericConfig.ClientConfig,
9294
cfg.StorageFactory,
95+
cfg.ExtraConfig,
9396
}
9497
return CompletedConfig{&c}
9598
}
@@ -121,11 +124,10 @@ func (config completedConfig) New() (*ClusterPediaServer, error) {
121124
resourceServerConfig.GenericConfig.ExternalAddress = config.GenericConfig.ExternalAddress
122125
resourceServerConfig.GenericConfig.LoopbackClientConfig = config.GenericConfig.LoopbackClientConfig
123126
resourceServerConfig.GenericConfig.TracerProvider = config.GenericConfig.TracerProvider
124-
resourceServerConfig.ExtraConfig = kubeapiserver.ExtraConfig{
125-
InformerFactory: clusterpediaInformerFactory,
126-
StorageFactory: config.StorageFactory,
127-
InitialAPIGroupResources: initialAPIGroupResources,
128-
}
127+
resourceServerConfig.InformerFactory = clusterpediaInformerFactory
128+
resourceServerConfig.StorageFactory = config.StorageFactory
129+
resourceServerConfig.InitialAPIGroupResources = initialAPIGroupResources
130+
resourceServerConfig.ExtraConfig = config.ExtraConfig
129131
kubeResourceAPIServer, methods, err := resourceServerConfig.Complete().New(genericapiserver.NewEmptyDelegate())
130132
if err != nil {
131133
return nil, err

pkg/kubeapiserver/apiserver.go

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,17 @@ func NewDefaultConfig() *Config {
6666
}
6767

6868
type ExtraConfig struct {
69-
StorageFactory storage.StorageFactory
70-
InformerFactory informers.SharedInformerFactory
71-
InitialAPIGroupResources []*restmapper.APIGroupResources
69+
AllowedProxySubresources map[schema.GroupResource]sets.Set[string]
7270
}
7371

7472
type Config struct {
7573
GenericConfig *genericapiserver.RecommendedConfig
7674

77-
ExtraConfig ExtraConfig
75+
StorageFactory storage.StorageFactory
76+
InformerFactory informers.SharedInformerFactory
77+
InitialAPIGroupResources []*restmapper.APIGroupResources
78+
79+
ExtraConfig *ExtraConfig
7880
}
7981

8082
func (c *Config) Complete() CompletedConfig {
@@ -83,8 +85,11 @@ func (c *Config) Complete() CompletedConfig {
8385
}
8486

8587
completed := &completedConfig{
86-
GenericConfig: c.GenericConfig.Complete(),
87-
ExtraConfig: &c.ExtraConfig,
88+
GenericConfig: c.GenericConfig.Complete(),
89+
StorageFactory: c.StorageFactory,
90+
InformerFactory: c.InformerFactory,
91+
InitialAPIGroupResources: c.InitialAPIGroupResources,
92+
ExtraConfig: c.ExtraConfig,
8893
}
8994

9095
c.GenericConfig.RequestInfoResolver = wrapRequestInfoResolverForNamespace{
@@ -96,7 +101,10 @@ func (c *Config) Complete() CompletedConfig {
96101
type completedConfig struct {
97102
GenericConfig genericapiserver.CompletedConfig
98103

99-
ExtraConfig *ExtraConfig
104+
StorageFactory storage.StorageFactory
105+
InformerFactory informers.SharedInformerFactory
106+
InitialAPIGroupResources []*restmapper.APIGroupResources
107+
ExtraConfig *ExtraConfig
100108
}
101109

102110
type CompletedConfig struct {
@@ -106,10 +114,10 @@ type CompletedConfig struct {
106114
var sortedMethods = []string{"GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"}
107115

108116
func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*genericapiserver.GenericAPIServer, []string, error) {
109-
if c.ExtraConfig.StorageFactory == nil {
117+
if c.StorageFactory == nil {
110118
return nil, nil, errors.New("kubeapiserver.New() called with config.StorageFactory == nil")
111119
}
112-
if c.ExtraConfig.InformerFactory == nil {
120+
if c.InformerFactory == nil {
113121
return nil, nil, errors.New("kubeapiserver.New() called with config.InformerFactory == nil")
114122
}
115123

@@ -123,7 +131,7 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
123131
delegate = http.NotFoundHandler()
124132
}
125133

126-
restManager := NewRESTManager(c.GenericConfig.Serializer, runtime.ContentTypeJSON, c.ExtraConfig.StorageFactory, c.ExtraConfig.InitialAPIGroupResources)
134+
restManager := NewRESTManager(c.GenericConfig.Serializer, runtime.ContentTypeJSON, c.StorageFactory, c.InitialAPIGroupResources)
127135
discoveryManager := discovery.NewDiscoveryManager(c.GenericConfig.Serializer, restManager, delegate)
128136

129137
// handle root discovery request
@@ -136,15 +144,20 @@ func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget)
136144
delegate: delegate,
137145
rest: restManager,
138146
discovery: discoveryManager,
139-
clusterLister: c.ExtraConfig.InformerFactory.Cluster().V1alpha2().PediaClusters().Lister(),
147+
clusterLister: c.InformerFactory.Cluster().V1alpha2().PediaClusters().Lister(),
140148
}
141149
genericserver.Handler.NonGoRestfulMux.HandlePrefix("/api/", resourceHandler)
142150
genericserver.Handler.NonGoRestfulMux.HandlePrefix("/apis/", resourceHandler)
143151

144-
controller := NewClusterResourceController(restManager, discoveryManager, c.ExtraConfig.InformerFactory.Cluster().V1alpha2().PediaClusters())
152+
controller := NewClusterResourceController(restManager, discoveryManager, c.InformerFactory.Cluster().V1alpha2().PediaClusters())
145153

146154
methodSet := sets.New("GET")
147155
for _, rest := range proxyrest.GetSubresourceRESTs(controller) {
156+
allows := c.ExtraConfig.AllowedProxySubresources[rest.ParentGroupResource()]
157+
if allows == nil || !allows.Has(rest.Subresource()) {
158+
continue
159+
}
160+
148161
if err := restManager.preRegisterSubresource(subresource{
149162
gr: rest.ParentGroupResource(),
150163
kind: rest.ParentKind(),

pkg/kubeapiserver/options.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package kubeapiserver
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/spf13/pflag"
8+
"k8s.io/apimachinery/pkg/runtime/schema"
9+
"k8s.io/apimachinery/pkg/util/sets"
10+
)
11+
12+
type Options struct {
13+
AllowedProxySubresources []string
14+
}
15+
16+
func NewOptions() *Options {
17+
return &Options{}
18+
}
19+
20+
func (o *Options) AddFlags(fs *pflag.FlagSet) {
21+
var resources []string
22+
for r, srs := range supportedProxyCoreSubresources {
23+
for _, sr := range srs {
24+
resources = append(resources, r+"/"+sr)
25+
}
26+
}
27+
fs.StringSliceVar(&o.AllowedProxySubresources, "allowed-proxy-subresources", o.AllowedProxySubresources, ""+
28+
"List of subresources that support proxying requests to the specified cluster, formatted as '[resource/subresource],[subresource],...'. "+
29+
fmt.Sprintf("Supported proxy subresources include %q", strings.Join(resources, ",")),
30+
)
31+
}
32+
33+
var supportedProxyCoreSubresources = map[string][]string{
34+
"pods": {"proxy", "log", "exec", "attach", "portfowrd"},
35+
"nodes": {"proxy"},
36+
"services": {"proxy"},
37+
}
38+
39+
func (o *Options) Config() (*ExtraConfig, error) {
40+
subresources := make(map[schema.GroupResource]sets.Set[string])
41+
42+
for _, subresource := range o.AllowedProxySubresources {
43+
var resource string
44+
switch slice := strings.Split(strings.TrimSpace(subresource), "/"); len(slice) {
45+
case 1:
46+
subresource = slice[0]
47+
case 2:
48+
resource, subresource = slice[0], slice[1]
49+
default:
50+
return nil, fmt.Errorf("--allowed-proxy-subresources: invalid format %q", subresource)
51+
}
52+
53+
var matched bool
54+
for r, srs := range supportedProxyCoreSubresources {
55+
for _, sr := range srs {
56+
if (resource == "" || resource == r) && subresource == sr {
57+
gr := schema.GroupResource{Group: "", Resource: r}
58+
set := subresources[gr]
59+
if set == nil {
60+
set = sets.New[string]()
61+
subresources[gr] = set
62+
}
63+
set.Insert(sr)
64+
matched = true
65+
break
66+
}
67+
}
68+
}
69+
if !matched {
70+
return nil, fmt.Errorf("--allowed-proxy-subresources: unsupported subresources or invalid format %q", subresource)
71+
}
72+
}
73+
return &ExtraConfig{AllowedProxySubresources: subresources}, nil
74+
}

0 commit comments

Comments
 (0)