Skip to content

Commit 07fd8db

Browse files
committed
Serve EditorTemplate via the editor.ui.k8s.appscode.com group
Add a registry storage for the new editor.ui.k8s.appscode.com EditorTemplate kind. It wraps kubepack.dev/lib-app/pkg/editor (CreateAppReleaseIfMissing + LoadResourceEditorModel / loadEditorModel2) and returns the loaded editor manifest, values and resources for an existing installation. Served under a new editor.ui.k8s.appscode.com aggregated API group. Bumps resource-metadata for the EditorTemplate type. Signed-off-by: Tamal Saha <tamal@appscode.com>
1 parent 57d4787 commit 07fd8db

828 files changed

Lines changed: 23004 additions & 1729 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ require (
4747
kmodules.xyz/go-containerregistry v0.0.15
4848
kmodules.xyz/monitoring-agent-api v0.34.3
4949
kmodules.xyz/offshoot-api v0.34.0
50-
kmodules.xyz/resource-metadata v0.47.1-0.20260626123515-f3c8c1fb4e83
50+
kmodules.xyz/resource-metadata v0.47.1-0.20260626193907-8312d452fb24
5151
kmodules.xyz/resource-metrics v0.34.4-0.20260626131047-afdc9726717d
5252
kmodules.xyz/resource-metrics/utils v0.34.1-0.20260622121456-42ed2b0a80a4
5353
kmodules.xyz/sets v0.29.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,8 +1187,8 @@ kmodules.xyz/monitoring-agent-api v0.34.3 h1:8dCTSatkKbi9CTAQ3+u7OmoyUghLvKTqqcl
11871187
kmodules.xyz/monitoring-agent-api v0.34.3/go.mod h1:0WtVdliczkCmjA/QyB2ZriVwABSA8Fhzt01yMEukFLY=
11881188
kmodules.xyz/offshoot-api v0.34.0 h1:HnOOp8FrCjTWjtNApRDo6Ahe79tOlLrJmyye4xxO4Kk=
11891189
kmodules.xyz/offshoot-api v0.34.0/go.mod h1:F+B59yYw4CZJ4uD4xu6C+mMLzIXUtuH7E+SbDICl9jE=
1190-
kmodules.xyz/resource-metadata v0.47.1-0.20260626123515-f3c8c1fb4e83 h1:TDMAyTYHY12VRXwq471jqsUI5VBu/8X9E9ZOMLrlW4g=
1191-
kmodules.xyz/resource-metadata v0.47.1-0.20260626123515-f3c8c1fb4e83/go.mod h1:ejz7IVjhqmj6VH8CVfprocJK/IM++OeunrfUp51ZrIw=
1190+
kmodules.xyz/resource-metadata v0.47.1-0.20260626193907-8312d452fb24 h1:SEcNvePGyg1KOH4TfuESwhIWeDqSUGW8o3ZQl18MsQA=
1191+
kmodules.xyz/resource-metadata v0.47.1-0.20260626193907-8312d452fb24/go.mod h1:ejz7IVjhqmj6VH8CVfprocJK/IM++OeunrfUp51ZrIw=
11921192
kmodules.xyz/resource-metrics v0.34.4-0.20260626131047-afdc9726717d h1:vgDVnRBzVuhbhlHYi8VWL/mJ8LHNk+z5ipVjIpTA2N4=
11931193
kmodules.xyz/resource-metrics v0.34.4-0.20260626131047-afdc9726717d/go.mod h1:R34IKtp5+NqcQz7AQJheBJK6Iem0LqrCbm/55Mn+ECQ=
11941194
kmodules.xyz/resource-metrics/utils v0.34.1-0.20260622121456-42ed2b0a80a4 h1:AhuMryuO4hKbnqH7QyVciCar8mQ2WYPqP0f1WVqzALQ=

pkg/apiserver/apiserver.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import (
4343
resourcesservicestorage "kubeops.dev/ui-server/pkg/registry/core/resourceservice"
4444
resourcesummarystorage "kubeops.dev/ui-server/pkg/registry/core/resourcesummary"
4545
coststorage "kubeops.dev/ui-server/pkg/registry/cost/reports"
46+
editortemplatestorage "kubeops.dev/ui-server/pkg/registry/editor/editortemplate"
4647
audittokenreqstorage "kubeops.dev/ui-server/pkg/registry/identity/audittokenrequest"
4748
clusteridstorage "kubeops.dev/ui-server/pkg/registry/identity/clusteridentity"
4849
inboxtokenreqstorage "kubeops.dev/ui-server/pkg/registry/identity/inboxtokenrequest"
@@ -101,6 +102,8 @@ import (
101102
promclient "kmodules.xyz/monitoring-agent-api/client"
102103
rscoreinstall "kmodules.xyz/resource-metadata/apis/core/install"
103104
rscoreapi "kmodules.xyz/resource-metadata/apis/core/v1alpha1"
105+
editorinstall "kmodules.xyz/resource-metadata/apis/editor/install"
106+
editorapi "kmodules.xyz/resource-metadata/apis/editor/v1alpha1"
104107
identityinstall "kmodules.xyz/resource-metadata/apis/identity/install"
105108
identityapi "kmodules.xyz/resource-metadata/apis/identity/v1alpha1"
106109
mgmtinstall "kmodules.xyz/resource-metadata/apis/management/install"
@@ -133,6 +136,7 @@ func init() {
133136
costinstall.Install(Scheme)
134137
rsinstall.Install(Scheme)
135138
uiinstall.Install(Scheme)
139+
editorinstall.Install(Scheme)
136140
rscoreinstall.Install(Scheme)
137141
mgmtinstall.Install(Scheme)
138142
crdinstall.Install(Scheme)
@@ -431,6 +435,17 @@ func (c completedConfig) New(ctx context.Context) (*UIServer, error) {
431435
return nil, err
432436
}
433437
}
438+
{
439+
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(editorapi.SchemeGroupVersion.Group, Scheme, metav1.ParameterCodec, Codecs)
440+
441+
v1alpha1storage := map[string]rest.Storage{}
442+
v1alpha1storage[editorapi.ResourceEditorTemplates] = editortemplatestorage.NewStorage(ctrlClient, cfg)
443+
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1storage
444+
445+
if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
446+
return nil, err
447+
}
448+
}
434449
{
435450
// Create metrics handler and fill the stores with metrics store
436451
// containing Help and Type headers of metrics
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package editortemplate
18+
19+
import (
20+
"context"
21+
"encoding/json"
22+
"fmt"
23+
"strings"
24+
25+
apierrors "k8s.io/apimachinery/pkg/api/errors"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"k8s.io/apimachinery/pkg/runtime"
28+
"k8s.io/apimachinery/pkg/runtime/schema"
29+
"k8s.io/apiserver/pkg/registry/rest"
30+
restclient "k8s.io/client-go/rest"
31+
editorapi "kmodules.xyz/resource-metadata/apis/editor/v1alpha1"
32+
"kubepack.dev/lib-app/pkg/editor"
33+
"kubepack.dev/lib-helm/pkg/repo"
34+
"sigs.k8s.io/controller-runtime/pkg/client"
35+
releasesapi "x-helm.dev/apimachinery/apis/releases/v1alpha1"
36+
)
37+
38+
type Storage struct {
39+
kc client.Client
40+
cfg *restclient.Config
41+
}
42+
43+
var (
44+
_ rest.GroupVersionKindProvider = &Storage{}
45+
_ rest.Scoper = &Storage{}
46+
_ rest.Storage = &Storage{}
47+
_ rest.Creater = &Storage{}
48+
_ rest.SingularNameProvider = &Storage{}
49+
)
50+
51+
func NewStorage(kc client.Client, cfg *restclient.Config) *Storage {
52+
return &Storage{kc: kc, cfg: cfg}
53+
}
54+
55+
func (r *Storage) GroupVersionKind(_ schema.GroupVersion) schema.GroupVersionKind {
56+
return editorapi.SchemeGroupVersion.WithKind(editorapi.ResourceKindEditorTemplate)
57+
}
58+
59+
func (r *Storage) NamespaceScoped() bool {
60+
return false
61+
}
62+
63+
func (r *Storage) GetSingularName() string {
64+
return strings.ToLower(editorapi.ResourceKindEditorTemplate)
65+
}
66+
67+
func (r *Storage) New() runtime.Object {
68+
return &editorapi.EditorTemplate{}
69+
}
70+
71+
func (r *Storage) Destroy() {}
72+
73+
var DefaultCache = repo.DefaultDiskCache()
74+
75+
func NewRegistry(kc client.Client) repo.IRegistry {
76+
return repo.NewRegistry(kc, DefaultCache)
77+
}
78+
79+
func (r *Storage) Create(ctx context.Context, obj runtime.Object, _ rest.ValidateObjectFunc, _ *metav1.CreateOptions) (runtime.Object, error) {
80+
in, ok := obj.(*editorapi.EditorTemplate)
81+
if !ok {
82+
return nil, fmt.Errorf("invalid object type: %T", obj)
83+
}
84+
if in.Request == nil {
85+
return nil, apierrors.NewBadRequest("missing request")
86+
}
87+
88+
reg := NewRegistry(r.kc)
89+
md := in.Request.ModelMetadata
90+
91+
if _, err := editor.CreateAppReleaseIfMissing(r.cfg, r.kc, reg, md.Metadata); err != nil {
92+
return nil, err
93+
}
94+
95+
var (
96+
tpl *releasesapi.EditorTemplate
97+
err error
98+
)
99+
if in.Request.ChartRef != nil {
100+
tpl, err = editor.LoadEditorModel(r.kc, reg, in.Request.ChartRef.ToAPIObject(), md)
101+
} else {
102+
tpl, err = editor.LoadResourceEditorModel(r.kc, reg, md)
103+
}
104+
if err != nil {
105+
return nil, err
106+
}
107+
108+
resp := &editorapi.EditorTemplateResponse{
109+
Manifest: string(tpl.Manifest),
110+
}
111+
if tpl.Values != nil {
112+
raw, err := json.Marshal(tpl.Values)
113+
if err != nil {
114+
return nil, err
115+
}
116+
resp.Values = &runtime.RawExtension{Raw: raw}
117+
}
118+
for _, res := range tpl.Resources {
119+
item := editorapi.EditorTemplateResource{
120+
Filename: res.Filename,
121+
Key: res.Key,
122+
}
123+
if res.Data != nil {
124+
raw, err := json.Marshal(res.Data)
125+
if err != nil {
126+
return nil, err
127+
}
128+
item.Data = &runtime.RawExtension{Raw: raw}
129+
}
130+
resp.Resources = append(resp.Resources, item)
131+
}
132+
in.Response = resp
133+
134+
return in, nil
135+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package editor
18+
19+
const (
20+
GroupName = "editor.ui.k8s.appscode.com"
21+
)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package install
18+
19+
import (
20+
"kmodules.xyz/resource-metadata/apis/editor/v1alpha1"
21+
22+
"k8s.io/apimachinery/pkg/runtime"
23+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
24+
)
25+
26+
// Install registers the API group and adds types to a scheme
27+
func Install(scheme *runtime.Scheme) {
28+
utilruntime.Must(v1alpha1.AddToScheme(scheme))
29+
utilruntime.Must(scheme.SetVersionPriority(v1alpha1.SchemeGroupVersion))
30+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package v1alpha1 is the v1alpha1 version of the API.
18+
19+
// +k8s:deepcopy-gen=package,register
20+
// +k8s:openapi-gen=true
21+
// +k8s:defaulter-gen=TypeMeta
22+
// +groupName=editor.ui.k8s.appscode.com
23+
package v1alpha1
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha1
18+
19+
import (
20+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
21+
"k8s.io/apimachinery/pkg/runtime"
22+
releasesapi "x-helm.dev/apimachinery/apis/releases/v1alpha1"
23+
)
24+
25+
const (
26+
ResourceKindEditorTemplate = "EditorTemplate"
27+
ResourceEditorTemplate = "editortemplate"
28+
ResourceEditorTemplates = "editortemplates"
29+
)
30+
31+
// EditorTemplate loads the editor model, manifest and resources for an existing
32+
// installation identified by its metadata. It is the aggregated-API equivalent
33+
// of kubepack.dev/lib-app/pkg/editor.LoadResourceEditorModel (see
34+
// chart_template.go loadEditorModel2).
35+
//
36+
// +genclient
37+
// +genclient:nonNamespaced
38+
// +genclient:onlyVerbs=create
39+
// +k8s:openapi-gen=true
40+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
41+
// +kubebuilder:object:root=true
42+
// +kubebuilder:resource:scope=Cluster
43+
type EditorTemplate struct {
44+
metav1.TypeMeta `json:",inline"`
45+
// Request identifies the installation to load.
46+
// +optional
47+
Request *EditorTemplateRequest `json:"request,omitempty"`
48+
// Response holds the loaded editor template.
49+
// +optional
50+
Response *EditorTemplateResponse `json:"response,omitempty"`
51+
}
52+
53+
type EditorTemplateRequest struct {
54+
releasesapi.ModelMetadata `json:",inline"`
55+
// ChartRef optionally selects the chart source. When unset, the resource
56+
// editor chart resolved from the metadata resource is used.
57+
// +optional
58+
ChartRef *releasesapi.ChartSourceFlatRef `json:"chartRef,omitempty"`
59+
}
60+
61+
type EditorTemplateResponse struct {
62+
// Manifest is the rendered manifest of the existing installation.
63+
// +optional
64+
Manifest string `json:"manifest,omitempty"`
65+
// Values is the editor model (values) of the existing installation.
66+
// +optional
67+
Values *runtime.RawExtension `json:"values,omitempty"`
68+
// Resources holds the individual resources of the existing installation.
69+
// +optional
70+
Resources []EditorTemplateResource `json:"resources,omitempty"`
71+
}
72+
73+
type EditorTemplateResource struct {
74+
// +optional
75+
Filename string `json:"filename,omitempty"`
76+
// +optional
77+
Key string `json:"key,omitempty"`
78+
// +optional
79+
Data *runtime.RawExtension `json:"data,omitempty"`
80+
}

0 commit comments

Comments
 (0)