Skip to content

Commit b38a855

Browse files
Implement database expose util (#40)
Signed-off-by: Arnob kumar saha <arnob@appscode.com>
1 parent 254043f commit b38a855

14 files changed

Lines changed: 1868 additions & 0 deletions

File tree

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ require (
245245
gopkg.in/yaml.v2 v2.4.0 // indirect
246246
gopkg.in/yaml.v3 v3.0.1 // indirect
247247
k8s.io/apiextensions-apiserver v0.34.3 // indirect
248+
k8s.io/apiserver v0.34.3 // indirect
248249
k8s.io/component-base v0.34.3 // indirect
249250
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
250251
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,8 @@ github.com/klauspost/cpuid/v2 v2.2.11 h1:0OwqZRYI2rFrjS4kvkDnqJkKHdHaRnCm68/DY4O
408408
github.com/klauspost/cpuid/v2 v2.2.11/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
409409
github.com/klauspost/crc32 v1.3.0 h1:sSmTt3gUt81RP655XGZPElI0PelVTZ6YwCRnPSupoFM=
410410
github.com/klauspost/crc32 v1.3.0/go.mod h1:D7kQaZhnkX/Y0tstFGf8VUzv2UofNGqCjnC3zdHB0Hw=
411+
github.com/kmodules/apiserver v0.34.4-0.20251227112449-07fa35efc6fc h1:R5bKc1c8Qu7z+7+O0xNWxIPjCYuaHUVZ+dSfeCZEd+c=
412+
github.com/kmodules/apiserver v0.34.4-0.20251227112449-07fa35efc6fc/go.mod h1:QPnnahMO5C2m3lm6fPW3+JmyQbvHZQ8uudAu/493P2w=
411413
github.com/kmodules/controller-runtime v0.22.5-0.20251227114913-f011264689cd h1:cpLV7Pr+pSo3kDYY4HsLZfbdF1WPQuPTP+Jo3hyoWzw=
412414
github.com/kmodules/controller-runtime v0.22.5-0.20251227114913-f011264689cd/go.mod h1:+QX1XUpTXN4mLoblf4tqr5CQcyHPAki2HLXqQMY6vh8=
413415
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=

pkg/cmds/expose/expose.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the AppsCode Community License 1.0.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+
https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md
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 expose
18+
19+
import (
20+
"go.bytebuilders.dev/cli/pkg/cmds/expose/gateway"
21+
22+
"github.com/spf13/cobra"
23+
"k8s.io/cli-runtime/pkg/genericclioptions"
24+
cmdutil "k8s.io/kubectl/pkg/cmd/util"
25+
)
26+
27+
func NewCmdExpose() *cobra.Command {
28+
cmd := &cobra.Command{
29+
Use: "expose",
30+
Short: "Expose databases",
31+
DisableAutoGenTag: true,
32+
}
33+
34+
kubeConfigFlags := genericclioptions.NewConfigFlags(true).WithDeprecatedPasswordFlag()
35+
matchVersionKubeConfigFlags := cmdutil.NewMatchVersionFlags(kubeConfigFlags)
36+
f := cmdutil.NewFactory(matchVersionKubeConfigFlags)
37+
38+
cmd.AddCommand(gateway.NewCmdGateway(f))
39+
40+
return cmd
41+
}

pkg/cmds/expose/gateway/gatway.go

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
/*
2+
Copyright AppsCode Inc. and Contributors
3+
4+
Licensed under the AppsCode Community License 1.0.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+
https://github.com/appscode/licenses/raw/1.0.0/AppsCode-Community-1.0.0.md
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 gateway
18+
19+
import (
20+
"context"
21+
"log"
22+
23+
catalogapi "go.bytebuilders.dev/catalog/api/catalog/v1alpha1"
24+
catgwapi "go.bytebuilders.dev/catalog/api/gateway/v1alpha1"
25+
26+
"github.com/spf13/cobra"
27+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29+
"k8s.io/apimachinery/pkg/runtime"
30+
"k8s.io/apimachinery/pkg/runtime/schema"
31+
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
32+
"k8s.io/client-go/discovery"
33+
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
34+
"k8s.io/client-go/rest"
35+
"k8s.io/klog/v2"
36+
cmdutil "k8s.io/kubectl/pkg/cmd/util"
37+
kutil "kmodules.xyz/client-go"
38+
cu "kmodules.xyz/client-go/client"
39+
dbapi "kubedb.dev/apimachinery/apis/kubedb/v1"
40+
kubedbscheme "kubedb.dev/apimachinery/client/clientset/versioned/scheme"
41+
"sigs.k8s.io/controller-runtime/pkg/client"
42+
)
43+
44+
var scheme = runtime.NewScheme()
45+
46+
func init() {
47+
utilruntime.Must(clientgoscheme.AddToScheme(scheme))
48+
utilruntime.Must(catalogapi.AddToScheme(scheme))
49+
utilruntime.Must(catgwapi.AddToScheme(scheme))
50+
utilruntime.Must(kubedbscheme.AddToScheme(scheme))
51+
}
52+
53+
func NewCmdGateway(f cmdutil.Factory) *cobra.Command {
54+
opt := newGatewayOpts(f)
55+
cmd := &cobra.Command{
56+
Use: "gateway",
57+
Short: "Gateway related info",
58+
DisableAutoGenTag: true,
59+
RunE: func(cmd *cobra.Command, args []string) error {
60+
return opt.run()
61+
},
62+
}
63+
64+
cmd.Flags().StringVarP(&opt.db.resource, "db-type", "t", "mongodb", "Database type")
65+
cmd.Flags().StringVarP(&opt.db.name, "name", "m", "mg-test", "Database name")
66+
cmd.Flags().StringVarP(&opt.db.namespace, "namespace", "n", "demo", "Database namespace")
67+
return cmd
68+
}
69+
70+
type gatewayOpts struct {
71+
kc client.Client
72+
disc *discovery.DiscoveryClient
73+
config *rest.Config
74+
db dbInfo
75+
76+
mapResourceToKind map[string]string
77+
mapSingularToKind map[string]string
78+
}
79+
80+
type dbInfo struct {
81+
resource string
82+
name string
83+
namespace string
84+
}
85+
86+
func newGatewayOpts(f cmdutil.Factory) *gatewayOpts {
87+
config, err := f.ToRESTConfig()
88+
if err != nil {
89+
log.Fatal(err)
90+
}
91+
kc, err := client.New(config, client.Options{Scheme: scheme})
92+
if err != nil {
93+
log.Fatalf("failed to create client: %v", err)
94+
}
95+
96+
disc, err := discovery.NewDiscoveryClientForConfig(config)
97+
if err != nil {
98+
log.Fatal("creating discovery client: %w", err)
99+
}
100+
101+
return &gatewayOpts{kc: kc, config: config, disc: disc}
102+
}
103+
104+
func (g *gatewayOpts) run() error {
105+
err := g.initMap()
106+
if err != nil {
107+
return err
108+
}
109+
kind := g.resolveKind(g.db.resource) + "Binding"
110+
var binding unstructured.Unstructured
111+
binding.SetGroupVersionKind(schema.GroupVersionKind{
112+
Group: catalogapi.GroupVersion.Group,
113+
Version: catalogapi.GroupVersion.Version,
114+
Kind: kind,
115+
})
116+
binding.SetNamespace(g.db.namespace)
117+
binding.SetName(g.db.name)
118+
119+
// Set spec.sourceRef
120+
sourceRef := map[string]any{
121+
"name": g.db.name,
122+
}
123+
124+
if g.db.namespace != "" {
125+
sourceRef["namespace"] = g.db.namespace
126+
}
127+
128+
if err := unstructured.SetNestedField(binding.Object, sourceRef, "spec", "sourceRef"); err != nil {
129+
return err
130+
}
131+
132+
vt, err := cu.CreateOrPatch(context.TODO(), g.kc, &binding, func(obj client.Object, createOp bool) client.Object {
133+
return obj
134+
// in := obj.(*catalogapi.BindingInterface)
135+
// return in
136+
})
137+
if vt != kutil.VerbUnchanged {
138+
klog.Infof("%s/%s of kind %s has been %s", g.db.namespace, g.db.name, kind, vt)
139+
}
140+
return err
141+
}
142+
143+
func (g *gatewayOpts) initMap() error {
144+
preferredResources, err := g.disc.ServerPreferredResources()
145+
if err != nil && !discovery.IsGroupDiscoveryFailedError(err) {
146+
return err
147+
}
148+
149+
g.mapSingularToKind = make(map[string]string)
150+
g.mapResourceToKind = make(map[string]string)
151+
152+
for _, p := range preferredResources {
153+
// if p.GroupVersionKind().Group != dbapi.SchemeGroupVersion.Group {continue }
154+
// This can't be done. Cause p.GroupVersionKind() is empty somehow
155+
for _, res := range p.APIResources {
156+
if res.Group != dbapi.SchemeGroupVersion.Group {
157+
continue
158+
}
159+
g.entry(res)
160+
}
161+
}
162+
return nil
163+
}
164+
165+
func (g *gatewayOpts) entry(res metav1.APIResource) {
166+
g.mapResourceToKind[res.Name] = res.Kind
167+
g.mapSingularToKind[res.SingularName] = res.Kind
168+
}
169+
170+
func (g *gatewayOpts) resolveKind(s string) string {
171+
val, exists := g.mapSingularToKind[s]
172+
if exists {
173+
return val
174+
}
175+
val, exists = g.mapResourceToKind[s]
176+
if exists {
177+
return val
178+
}
179+
return s
180+
}

pkg/cmds/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"go.bytebuilders.dev/cli/pkg/cmds/cluster"
2727
cmdconfig "go.bytebuilders.dev/cli/pkg/cmds/config"
2828
"go.bytebuilders.dev/cli/pkg/cmds/debug"
29+
"go.bytebuilders.dev/cli/pkg/cmds/expose"
2930
"go.bytebuilders.dev/cli/pkg/cmds/installer"
3031
"go.bytebuilders.dev/cli/pkg/config"
3132
ace "go.bytebuilders.dev/client"
@@ -56,6 +57,7 @@ func NewRootCmd() *cobra.Command {
5657

5758
rootCmd.AddCommand(installer.NewCmdInstaller())
5859
rootCmd.AddCommand(debug.NewCmdDebug())
60+
rootCmd.AddCommand(expose.NewCmdExpose())
5961

6062
rootCmd.AddCommand(v.NewCmdVersion())
6163
rootCmd.AddCommand(NewCmdCompletion())

0 commit comments

Comments
 (0)