...

Source file src/github.com/redhat-developer/odo/pkg/binding/add.go

Documentation: github.com/redhat-developer/odo/pkg/binding

     1  package binding
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  
     8  	"github.com/devfile/library/v2/pkg/devfile/parser"
     9  	"gopkg.in/yaml.v2"
    10  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    11  	"k8s.io/apimachinery/pkg/runtime/schema"
    12  
    13  	sboApi "github.com/redhat-developer/service-binding-operator/apis/binding/v1alpha1"
    14  
    15  	"github.com/redhat-developer/odo/pkg/binding/asker"
    16  	backendpkg "github.com/redhat-developer/odo/pkg/binding/backend"
    17  	"github.com/redhat-developer/odo/pkg/kclient"
    18  	"github.com/redhat-developer/odo/pkg/libdevfile"
    19  )
    20  
    21  func (o *BindingClient) SelectNamespace(flags map[string]string) (string, error) {
    22  	var backend backendpkg.AddBindingBackend
    23  	if len(flags) == 0 {
    24  		backend = o.interactiveBackend
    25  	} else {
    26  		backend = o.flagsBackend
    27  	}
    28  	return backend.SelectNamespace(flags)
    29  }
    30  
    31  // ValidateAddBinding calls Validate method of the adequate backend and then checks if the ServiceBinding Operator is installed in the cluster.
    32  func (o *BindingClient) ValidateAddBinding(flags map[string]string, withDevfile bool) error {
    33  	var backend backendpkg.AddBindingBackend
    34  	if len(flags) == 0 {
    35  		backend = o.interactiveBackend
    36  	} else {
    37  		backend = o.flagsBackend
    38  	}
    39  	err := backend.Validate(flags, withDevfile)
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	return o.checkServiceBindingOperatorInstalled()
    45  }
    46  
    47  func (o *BindingClient) SelectServiceInstance(flags map[string]string, serviceMap map[string]unstructured.Unstructured) (string, error) {
    48  	var backend backendpkg.AddBindingBackend
    49  	if len(flags) == 0 {
    50  		backend = o.interactiveBackend
    51  	} else {
    52  		backend = o.flagsBackend
    53  	}
    54  	return backend.SelectServiceInstance(flags[backendpkg.FLAG_SERVICE], serviceMap)
    55  }
    56  
    57  func (o *BindingClient) SelectWorkloadInstance(flags map[string]string) (string, schema.GroupVersionKind, error) {
    58  	var backend backendpkg.AddBindingBackend
    59  	if len(flags) == 0 {
    60  		backend = o.interactiveBackend
    61  	} else {
    62  		backend = o.flagsBackend
    63  	}
    64  	resource, gvk, err := backend.SelectWorkloadInstance(flags[backendpkg.FLAG_WORKLOAD])
    65  	if err != nil {
    66  		return "", schema.GroupVersionKind{}, err
    67  	}
    68  	return resource, gvk, nil
    69  }
    70  
    71  func (o *BindingClient) AskBindingName(serviceName, componentName string, flags map[string]string) (string, error) {
    72  	var backend backendpkg.AddBindingBackend
    73  	if len(flags) == 0 {
    74  		backend = o.interactiveBackend
    75  	} else {
    76  		backend = o.flagsBackend
    77  	}
    78  	defaultBindingName := fmt.Sprintf("%v-%v", componentName, serviceName)
    79  	return backend.AskBindingName(defaultBindingName, flags)
    80  }
    81  
    82  func (o *BindingClient) AskBindAsFiles(flags map[string]string) (bool, error) {
    83  	var backend backendpkg.AddBindingBackend
    84  	if len(flags) == 0 {
    85  		backend = o.interactiveBackend
    86  	} else {
    87  		backend = o.flagsBackend
    88  	}
    89  	return backend.AskBindAsFiles(flags)
    90  }
    91  
    92  func (o *BindingClient) AskNamingStrategy(flags map[string]string) (string, error) {
    93  	var backend backendpkg.AddBindingBackend
    94  	if len(flags) == 0 {
    95  		backend = o.interactiveBackend
    96  	} else {
    97  		backend = o.flagsBackend
    98  	}
    99  	return backend.AskNamingStrategy(flags)
   100  }
   101  
   102  func (o *BindingClient) AddBindingToDevfile(
   103  	componentName string,
   104  	bindingName string,
   105  	bindAsFiles bool,
   106  	serviceNs string,
   107  	namingStrategy string,
   108  	unstructuredService unstructured.Unstructured,
   109  	obj parser.DevfileObj,
   110  ) (parser.DevfileObj, error) {
   111  	service, err := o.kubernetesClient.NewServiceBindingServiceObject(serviceNs, unstructuredService, bindingName)
   112  	if err != nil {
   113  		return obj, err
   114  	}
   115  
   116  	deploymentName := fmt.Sprintf("%s-app", componentName)
   117  	deploymentGVK, err := o.kubernetesClient.GetDeploymentAPIVersion()
   118  	if err != nil {
   119  		return obj, err
   120  	}
   121  
   122  	serviceBinding := kclient.NewServiceBindingObject(
   123  		bindingName, bindAsFiles, deploymentName, namingStrategy, deploymentGVK, []sboApi.Mapping{}, []sboApi.Service{service}, sboApi.ServiceBindingStatus{})
   124  
   125  	// Note: we cannot directly marshal the serviceBinding object to yaml because it doesn't do that in the correct k8s manifest format
   126  	serviceBindingUnstructured, err := kclient.ConvertK8sResourceToUnstructured(serviceBinding)
   127  	if err != nil {
   128  		return obj, err
   129  	}
   130  	yamlDesc, err := yaml.Marshal(serviceBindingUnstructured.UnstructuredContent())
   131  	if err != nil {
   132  		return obj, err
   133  	}
   134  
   135  	return libdevfile.AddKubernetesComponentToDevfile(string(yamlDesc), serviceBinding.Name, obj)
   136  }
   137  
   138  func (o *BindingClient) AddBinding(
   139  	flags map[string]string,
   140  	bindingName string,
   141  	bindAsFiles bool,
   142  	serviceNs string,
   143  	namingStrategy string,
   144  	unstructuredService unstructured.Unstructured,
   145  	workloadName string,
   146  	workloadGVK schema.GroupVersionKind,
   147  ) ([]asker.CreationOption, string, string, error) {
   148  	service, err := o.kubernetesClient.NewServiceBindingServiceObject(serviceNs, unstructuredService, bindingName)
   149  	if err != nil {
   150  		return nil, "", "", err
   151  	}
   152  
   153  	serviceBinding := kclient.NewServiceBindingObject(
   154  		bindingName, bindAsFiles, workloadName, namingStrategy, workloadGVK, []sboApi.Mapping{}, []sboApi.Service{service}, sboApi.ServiceBindingStatus{})
   155  
   156  	var backend backendpkg.AddBindingBackend
   157  	if len(flags) == 0 {
   158  		backend = o.interactiveBackend
   159  	} else {
   160  		backend = o.flagsBackend
   161  	}
   162  
   163  	var options []asker.CreationOption
   164  	for len(options) == 0 {
   165  		options, err = backend.SelectCreationOptions(flags)
   166  		if err != nil {
   167  			return nil, "", "", err
   168  		}
   169  	}
   170  
   171  	// Note: we cannot directly marshal the serviceBinding object to yaml because it doesn't do that in the correct k8s manifest format
   172  	serviceBindingUnstructured, err := kclient.ConvertK8sResourceToUnstructured(serviceBinding)
   173  	if err != nil {
   174  		return nil, "", "", err
   175  	}
   176  	yamlDesc, err := yaml.Marshal(serviceBindingUnstructured.UnstructuredContent())
   177  	if err != nil {
   178  		return nil, "", "", err
   179  	}
   180  
   181  	var filename string
   182  	for _, option := range options {
   183  		if option == asker.OutputToFile {
   184  			filename, err = backend.AskOutputFilePath(flags, filepath.Join("kubernetes", serviceBinding.GetName()+".yaml"))
   185  			if err != nil {
   186  				return nil, "", "", err
   187  			}
   188  			break
   189  		}
   190  	}
   191  
   192  	var output string
   193  	for _, option := range options {
   194  		switch option {
   195  		case asker.OutputToFile:
   196  			err = os.MkdirAll(filepath.Dir(filename), 0750)
   197  			if err != nil {
   198  				return nil, "", "", err
   199  			}
   200  			err = os.WriteFile(filename, yamlDesc, 0600)
   201  			if err != nil {
   202  				return nil, "", "", err
   203  			}
   204  
   205  		case asker.OutputToStdout:
   206  			output = string(yamlDesc)
   207  
   208  		case asker.CreateOnCluster:
   209  			_, err = o.kubernetesClient.PatchDynamicResource(serviceBindingUnstructured)
   210  			if err != nil {
   211  				return nil, "", "", err
   212  			}
   213  		}
   214  	}
   215  
   216  	return options, output, filename, nil
   217  }
   218  

View as plain text