Skip to content

Commit f732c81

Browse files
committed
chore: refactor logic to use additional flags
1 parent eacc37e commit f732c81

File tree

6 files changed

+101
-66
lines changed

6 files changed

+101
-66
lines changed

cmd/rhoas/pkged.go

Lines changed: 0 additions & 12 deletions
This file was deleted.

docs/commands/rhoas_cluster_bind.adoc

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

locales/cluster/bind/active.en.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[cluster.serviceBinding.namespaceInfo]
2-
one = '"Namespace not provided. Using {{.Namespace}} namespace'
2+
one = 'Namespace not provided. Using {{.Namespace}} namespace'
33

44
[cluster.serviceBinding.confirm.message]
55
one = 'Do you want to continue?'

locales/cmd/cluster/bind/active.en.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ $ rhoas cluster bind --namespace=ns --app-name=myapp
2929
[cluster.bind.flag.appName]
3030
one = '''Name of the kubernetes deployment to bind'''
3131

32-
[cluster.bind.flag.onlyOperator.description]
32+
[cluster.bind.flag.forceOperator.description]
3333
one = '''Use ServiceBindingOperator only and fail if Operator is not installed'''
3434

35+
[cluster.bind.flag.forceSDK.description]
36+
one = '''Use Service Binding SDK and skip ServiceBindingOperator even if installed on the cluster'''
37+
38+
39+
3540
[cluster.bind.error.emptyResponse]
3641
one = '''Server returned empty response for service'''

pkg/cluster/serviceBinding.go

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,27 +2,26 @@ package cluster
22

33
import (
44
"context"
5+
"crypto/rand"
56
"errors"
67
"fmt"
78
"github.com/AlecAivazis/survey/v2"
9+
"github.com/redhat-developer/app-services-cli/internal/localizer"
810
"github.com/redhat-developer/app-services-cli/pkg/color"
911
"github.com/redhat-developer/app-services-cli/pkg/logging"
12+
"github.com/redhat-developer/service-binding-operator/api/v1alpha1"
13+
"github.com/redhat-developer/service-binding-operator/pkg/reconcile/pipeline/builder"
1014
sboContext "github.com/redhat-developer/service-binding-operator/pkg/reconcile/pipeline/context"
15+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1116
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1217
"k8s.io/apimachinery/pkg/runtime"
18+
"k8s.io/apimachinery/pkg/runtime/schema"
19+
"k8s.io/client-go/dynamic"
1320
"k8s.io/client-go/rest"
21+
"k8s.io/client-go/tools/clientcmd"
1422
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
1523
"os"
1624
"path/filepath"
17-
"time"
18-
19-
"github.com/redhat-developer/app-services-cli/internal/localizer"
20-
"github.com/redhat-developer/service-binding-operator/api/v1alpha1"
21-
"github.com/redhat-developer/service-binding-operator/pkg/reconcile/pipeline/builder"
22-
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23-
"k8s.io/apimachinery/pkg/runtime/schema"
24-
"k8s.io/client-go/dynamic"
25-
"k8s.io/client-go/tools/clientcmd"
2625
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
2726
)
2827

@@ -34,20 +33,28 @@ type KubernetesClients struct {
3433

3534
var deploymentResource = schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}
3635

37-
// TODO extract arguments
38-
func ExecuteServiceBinding(logger logging.Logger, serviceName string, ns string, appName string,
39-
forceCreationWithoutAsk bool, forceUseOperator bool) error {
36+
type ServiceBindingOptions struct {
37+
ServiceName string
38+
Namespace string
39+
AppName string
40+
ForceCreationWithoutAsk bool
41+
ForceUseOperator bool
42+
ForceUseSDK bool
43+
BindingName string
44+
}
45+
46+
func ExecuteServiceBinding(logger logging.Logger, options *ServiceBindingOptions) error {
4047
clients, err := client()
4148
if err != nil {
4249
return err
4350
}
44-
51+
ns := options.Namespace
4552
if ns == "" {
4653
ns, _, err = (*clients.clientConfig).Namespace()
4754
if err != nil {
4855
return err
4956
}
50-
logger.Info(&localizer.Config{
57+
logger.Info(localizer.Config{
5158
MessageID: "cluster.serviceBinding.namespaceInfo",
5259
TemplateData: map[string]interface{}{
5360
"Namespace": color.Info(ns),
@@ -56,22 +63,22 @@ func ExecuteServiceBinding(logger logging.Logger, serviceName string, ns string,
5663
}
5764

5865
// Get proper deployment
59-
if appName == "" {
60-
appName, err = fetchAppNameFromCluster(clients, ns)
66+
if options.AppName == "" {
67+
options.AppName, err = fetchAppNameFromCluster(clients, ns)
6168
if err != nil {
6269
return err
6370
}
6471
} else {
65-
_, err = clients.dynamicClient.Resource(deploymentResource).Namespace(ns).Get(context.TODO(), appName, metav1.GetOptions{})
72+
_, err = clients.dynamicClient.Resource(deploymentResource).Namespace(ns).Get(context.TODO(), options.AppName, metav1.GetOptions{})
6673
if err != nil {
6774
return err
6875
}
6976
}
7077

7178
// Print desired action
72-
logger.Info(fmt.Sprintf(localizer.MustLocalizeFromID("cluster.serviceBinding.status.message"), serviceName, appName))
79+
logger.Info(fmt.Sprintf(localizer.MustLocalizeFromID("cluster.serviceBinding.status.message"), options.ServiceName, options.AppName))
7380

74-
if !forceCreationWithoutAsk {
81+
if !options.ForceCreationWithoutAsk {
7582
var shouldContinue bool
7683
confirm := &survey.Confirm{
7784
Message: localizer.MustLocalizeFromID("cluster.serviceBinding.confirm.message"),
@@ -87,30 +94,29 @@ func ExecuteServiceBinding(logger logging.Logger, serviceName string, ns string,
8794
}
8895

8996
// Check KafkaConnection
90-
_, err = clients.dynamicClient.Resource(AKCResource).Namespace(ns).Get(context.TODO(), serviceName, metav1.GetOptions{})
97+
_, err = clients.dynamicClient.Resource(AKCResource).Namespace(ns).Get(context.TODO(), options.ServiceName, metav1.GetOptions{})
9198
if err != nil {
9299
return errors.New(localizer.MustLocalizeFromID("cluster.serviceBinding.serviceMissing.message"))
93100
}
94101

95102
// Execute binding
96-
err = performBinding(serviceName, appName, ns, clients, forceUseOperator, logger)
103+
err = performBinding(options, ns, clients, logger)
97104
if err != nil {
98105
return err
99106
}
100107

101-
logger.Info(fmt.Sprintf(localizer.MustLocalizeFromID("cluster.serviceBinding.bindingSuccess"), serviceName, appName))
108+
logger.Info(fmt.Sprintf(localizer.MustLocalizeFromID("cluster.serviceBinding.bindingSuccess"), options.ServiceName, options.AppName))
102109
return nil
103110
}
104111

105-
func performBinding(serviceName string, appName string, ns string, clients *KubernetesClients,
106-
forceUseOperator bool, logger logging.Logger) error {
112+
func performBinding(options *ServiceBindingOptions, ns string, clients *KubernetesClients, logger logging.Logger) error {
107113
serviceRef := v1alpha1.Service{
108114
NamespacedRef: v1alpha1.NamespacedRef{
109115
Ref: v1alpha1.Ref{
110116
Group: AKCResource.Group,
111117
Version: AKCResource.Version,
112118
Resource: AKCResource.Resource,
113-
Name: serviceName,
119+
Name: options.ServiceName,
114120
},
115121
},
116122
}
@@ -120,15 +126,23 @@ func performBinding(serviceName string, appName string, ns string, clients *Kube
120126
Group: deploymentResource.Group,
121127
Version: deploymentResource.Version,
122128
Resource: deploymentResource.Resource,
123-
Name: appName,
129+
Name: options.AppName,
124130
},
125131
}
126132

127-
now := time.Now()
133+
if options.BindingName == "" {
134+
randomValue := make([]byte, 4)
135+
_, err := rand.Read(randomValue)
136+
if err != nil {
137+
return err
138+
}
139+
options.BindingName = fmt.Sprintf("%v-%x", options.ServiceName, randomValue)
140+
}
141+
128142
sb := &v1alpha1.ServiceBinding{
129143
ObjectMeta: metav1.ObjectMeta{
130-
Name: fmt.Sprintf("%v-%v", serviceName, now.Unix()),
131-
Namespace: ns,
144+
Name: fmt.Sprintf("%v-%v", options.ServiceName, options.BindingName),
145+
Namespace: options.Namespace,
132146
},
133147
Spec: v1alpha1.ServiceBindingSpec{
134148
BindAsFiles: true,
@@ -138,26 +152,42 @@ func performBinding(serviceName string, appName string, ns string, clients *Kube
138152
}
139153
sb.SetGroupVersionKind(v1alpha1.GroupVersionKind)
140154

155+
if options.ForceUseSDK {
156+
return useSDKForBinding(clients, sb)
157+
}
158+
141159
// Check of operator is installed
142160
_, err := clients.dynamicClient.Resource(v1alpha1.GroupVersionResource).Namespace(ns).
143161
List(context.TODO(), metav1.ListOptions{Limit: 1})
144162

145163
if err != nil {
146-
if forceUseOperator {
164+
if options.ForceUseOperator {
147165
return errors.New(localizer.MustLocalizeFromID("cluster.serviceBinding.operatorMissing") + err.Error())
148166
}
149-
logger.Debug("Service binding Operator not available. Will use SDK")
150-
} else {
151-
logger.Info(localizer.MustLocalizeFromID("cluster.serviceBinding.usingOperator"))
152-
sbData, err := runtime.DefaultUnstructuredConverter.ToUnstructured(sb)
153-
unstructuredSB := unstructured.Unstructured{Object: sbData}
154-
_, err = clients.dynamicClient.Resource(v1alpha1.GroupVersionResource).Namespace(ns).
155-
Create(context.TODO(), &unstructuredSB, metav1.CreateOptions{})
167+
logger.Debug("Service binding Operator not available. Will use SDK option for binding")
168+
return useSDKForBinding(clients, sb)
169+
}
156170

171+
logger.Debug("Using Operator to perform binding")
172+
return useOperatorForBinding(logger, sb, clients, ns)
173+
174+
}
175+
176+
func useOperatorForBinding(logger logging.Logger, sb *v1alpha1.ServiceBinding, clients *KubernetesClients, ns string) error {
177+
logger.Info(localizer.MustLocalizeFromID("cluster.serviceBinding.usingOperator"))
178+
sbData, err := runtime.DefaultUnstructuredConverter.ToUnstructured(sb)
179+
if err != nil {
157180
return err
158181
}
159182

160-
// Use SDK instead of operatort
183+
unstructuredSB := unstructured.Unstructured{Object: sbData}
184+
_, err = clients.dynamicClient.Resource(v1alpha1.GroupVersionResource).Namespace(ns).
185+
Create(context.TODO(), &unstructuredSB, metav1.CreateOptions{})
186+
187+
return err
188+
}
189+
190+
func useSDKForBinding(clients *KubernetesClients, sb *v1alpha1.ServiceBinding) error {
161191
restMapper, err := apiutil.NewDynamicRESTMapper(clients.restConfig)
162192
if err != nil {
163193
return err

pkg/cmd/cluster/bind/bind.go

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ type Options struct {
2828
ignoreContext bool
2929
appName string
3030
selectedKafka string
31-
useOperator bool
31+
32+
forceOperator bool
33+
forceSDK bool
34+
bindingName string
3235
}
3336

3437
func NewBindCommand(f *factory.Factory) *cobra.Command {
@@ -70,13 +73,13 @@ func NewBindCommand(f *factory.Factory) *cobra.Command {
7073
cmd.Flags().BoolVarP(&opts.forceCreationWithoutAsk, "yes", "y", false, localizer.MustLocalizeFromID("cluster.common.flag.yes.description"))
7174
cmd.Flags().StringVarP(&opts.namespace, "namespace", "n", "", localizer.MustLocalizeFromID("cluster.common.flag.namespace.description"))
7275
cmd.Flags().BoolVarP(&opts.ignoreContext, "ignore-context", "", false, localizer.MustLocalizeFromID("cluster.common.flag.ignoreContext.description"))
73-
cmd.Flags().BoolVarP(&opts.useOperator, "force-operator", "", false, localizer.MustLocalizeFromID("cluster.bind.flag.onlyOperator.description"))
74-
76+
cmd.Flags().BoolVarP(&opts.forceOperator, "force-operator", "", false, localizer.MustLocalizeFromID("cluster.bind.flag.forceOperator.description"))
77+
cmd.Flags().BoolVarP(&opts.forceSDK, "force-sdk", "", false, localizer.MustLocalizeFromID("cluster.bind.flag.forceSDK.description"))
7578
return cmd
7679
}
7780

7881
func runBind(opts *Options) error {
79-
connection, err := opts.Connection(connection.DefaultConfigSkipMasAuth)
82+
apiConnection, err := opts.Connection(connection.DefaultConfigSkipMasAuth)
8083
if err != nil {
8184
return err
8285
}
@@ -94,7 +97,7 @@ func runBind(opts *Options) error {
9497
// In future config will include Id's of other services
9598
if cfg.Services.Kafka == nil || opts.ignoreContext {
9699
// nolint
97-
selectedKafka, err := kafka.InteractiveSelect(connection, logger)
100+
selectedKafka, err := kafka.InteractiveSelect(apiConnection, logger)
98101
if err != nil {
99102

100103
return err
@@ -104,22 +107,26 @@ func runBind(opts *Options) error {
104107
opts.selectedKafka = cfg.Services.Kafka.ClusterID
105108
}
106109

107-
api := connection.API()
108-
kafkaInstance, _, error := api.Kafka().GetKafkaById(context.Background(), opts.selectedKafka).Execute()
110+
api := apiConnection.API()
111+
kafkaInstance, _, err2 := api.Kafka().GetKafkaById(context.Background(), opts.selectedKafka).Execute()
109112

110-
if error != nil {
111-
return error
113+
if err2 != nil {
114+
return err2
112115
}
113116

114117
if kafkaInstance.Name == nil {
115118
return errors.New(localizer.MustLocalizeFromID("cluster.bind.error.emptyResponse"))
116119
}
117120

118-
err = cluster.ExecuteServiceBinding(logger, *kafkaInstance.Name,
119-
opts.namespace,
120-
opts.appName,
121-
opts.forceCreationWithoutAsk,
122-
opts.useOperator)
121+
err = cluster.ExecuteServiceBinding(logger, &cluster.ServiceBindingOptions{
122+
ServiceName: *kafkaInstance.Name,
123+
Namespace: opts.namespace,
124+
AppName: opts.appName,
125+
ForceCreationWithoutAsk: opts.forceCreationWithoutAsk,
126+
ForceUseOperator: opts.forceOperator,
127+
ForceUseSDK: opts.forceSDK,
128+
BindingName: opts.bindingName,
129+
})
123130

124131
return err
125132
}

0 commit comments

Comments
 (0)