ricardozanini commented on code in PR #2465:
URL: 
https://github.com/apache/incubator-kie-tools/pull/2465#discussion_r1724012662


##########
packages/kn-plugin-workflow/pkg/common/k8sclient/goapi.go:
##########
@@ -0,0 +1,192 @@
+package k8sclient
+
+import (
+       "context"
+       "fmt"
+       "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+       "os"
+       "path/filepath"
+
+       "k8s.io/apimachinery/pkg/api/meta"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/apimachinery/pkg/util/yaml"
+
+       "k8s.io/client-go/dynamic"
+       "k8s.io/client-go/kubernetes/scheme"
+       "k8s.io/client-go/rest"
+       "k8s.io/client-go/tools/clientcmd"
+       "k8s.io/client-go/tools/clientcmd/api"
+)
+
+type GoAPI struct{}
+
+func KubeApiConfig() (*api.Config, error) {
+       homeDir, err := os.UserHomeDir()
+       if err != nil {
+               return nil, fmt.Errorf("error getting user home dir: %w", err)
+       }
+       kubeConfigPath := filepath.Join(homeDir, ".kube", "config")
+       fmt.Printf("🔎 Using kubeconfig: %s\n", kubeConfigPath)
+       config, err := clientcmd.LoadFromFile(kubeConfigPath)
+       if err != nil {
+               return nil, fmt.Errorf("❌ ERROR: Failed to load kubeconfig: 
%w", err)
+       }
+       return config, nil
+}
+
+func KubeRestConfig() (*rest.Config, error) {
+       config, err := rest.InClusterConfig()
+       if err != nil {
+               homeDir, err := os.UserHomeDir()
+               if err != nil {
+                       return nil, fmt.Errorf("error getting user home dir: 
%w", err)
+               }
+               kubeConfigPath := filepath.Join(homeDir, ".kube", "config")
+               fmt.Printf("🔎 Using kubeconfig: %s\n", kubeConfigPath)
+               config, err = clientcmd.BuildConfigFromFlags("", kubeConfigPath)
+               if err != nil {
+                       return nil, fmt.Errorf("❌ ERROR: Failed to load 
kubeconfig: %w", err)
+               }
+       }
+       return config, nil
+}
+
+func (m GoAPI) GetKubectlNamespace() (string, error) {
+       fmt.Println("🔎 Checking current namespace in kubectl...")
+
+       config, err := KubeApiConfig()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: Failed to get current kubectl 
namespace: %w", err)
+       }
+       namespace := config.Contexts[config.CurrentContext].Namespace
+
+       if len(namespace) == 0 {
+               namespace = "default"
+       }
+       fmt.Printf(" - ✅  kubectl current namespace: %s\n", namespace)
+       return namespace, nil
+}
+
+func (m GoAPI) CheckKubectlContext() (string, error) {
+       config, err := KubeApiConfig()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found %w", err)
+       }
+       context := config.CurrentContext
+       if context == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found")
+       }
+       fmt.Printf(" - ✅ kubectl current context: %s\n", context)
+       return context, nil
+}
+
+func (m GoAPI) ExecuteKubectlApply(path, namespace string) error {
+       config, err := KubeRestConfig()
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to create rest config for 
Kubernetes client: %v", err)
+       }
+
+       client, err := dynamic.NewForConfig(config)
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to create dynamic Kubernetes 
client: %v", err)
+       }
+       fmt.Printf("🔨 Applying YAML file %s\n", path)
+       data, err := os.ReadFile(path)
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to read YAML file: %w", err)
+       }
+
+       obj, _, err := scheme.Codecs.UniversalDeserializer().Decode(data, nil, 
nil)
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to decode YAML: %w", err)
+       }
+
+       unstructuredObj, err := 
runtime.DefaultUnstructuredConverter.ToUnstructured(obj)
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to decode YAML: %w", err)
+       }
+
+       unstructuredMap := &unstructured.Unstructured{Object: unstructuredObj}
+       gvk := unstructuredMap.GroupVersionKind()
+       gvr, _ := meta.UnsafeGuessKindToResource(gvk)
+
+       var res dynamic.ResourceInterface
+       if namespace == "" {
+               res = client.Resource(gvr)
+       } else {
+               res = client.Resource(gvr).Namespace(namespace)
+       }
+
+       _, err = res.Create(context.Background(), unstructuredMap, 
metav1.CreateOptions{})
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to apply CRD: %w", err)
+       }
+       return nil
+}
+
+func (m GoAPI) ExecuteKubectlDelete(path, namespace string) error {

Review Comment:
   ```suggestion
   func (m GoAPI) ExecuteKubectlDelete(path, namespace string) error {
   ```
   
   You can remove the `kubectl` prefix from these operations now that you are 
using the Rest client directly. The only portion of the code that we should 
link to `kubectl` is when we look for the cluster rest configuration.



##########
packages/kn-plugin-workflow/pkg/common/k8sclient/kubectl.go:
##########
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package k8sclient
+
+import (
+       "bufio"
+       "bytes"
+       "fmt"
+       
"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata"
+       "os"
+       "os/exec"
+       "strings"
+)
+
+type KubeCtl struct{}
+
+func (m KubeCtl) GetKubectlNamespace() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+
+       fmt.Println("🔎 Checking current namespace in kubectl...")
+       cmd := exec.Command("kubectl", "config", "view", "--minify", 
"--output", "jsonpath={..namespace}")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: Failed to get current kubectl 
namespace: %w", err)
+       }
+       namespace := strings.TrimSpace(string(output))
+       if namespace == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl namespace 
found")
+       }
+       fmt.Printf(" - ✅  kubectl current namespace: %s\n", namespace)
+       return namespace, nil
+}
+
+func (m KubeCtl) CheckKubectlContext() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+       fmt.Println("🔎 Checking if kubectl has a context configured...")
+       cmd := exec.Command("kubectl", "config", "current-context")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found %w", err)
+       }
+       context := strings.TrimSpace(string(output))
+       if context == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found")
+       }
+       fmt.Printf(" - ✅ kubectl current context: %s \n", context)
+       return context, nil
+}
+
+func CheckKubectl() error {
+       fmt.Println("🔎 Checking if kubectl is available...")
+       _, kubectlCheck := exec.LookPath("kubectl")
+       if err := kubectlCheck; err != nil {
+               fmt.Println("ERROR: kubectl not found")
+               fmt.Println("kubectl is required for deploy")
+               fmt.Println("Download it from 
https://kubectl.docs.kubernetes.io/installation/kubectl/";)
+               return fmt.Errorf("❌ ERROR: kubectl not found %w", err)
+       }
+
+       fmt.Println(" - ✅ kubectl is available")
+       return nil
+}
+
+func (m KubeCtl) ExecuteKubectlApply(crd, namespace string) error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl",
+               "apply",
+               "-f", crd,
+               "-n", namespace,
+               "--validate=false")
+
+       var stderror bytes.Buffer
+
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = &stderror //os.Stderr
+
+       err := cmd.Run()
+       scanner := bufio.NewScanner(&stderror)
+       for scanner.Scan() {
+               line := scanner.Text()
+               //Temporarily removing the following warning:
+               //In this context, using apply or create are interchangeable, 
but generates a warning.
+               //Warning: resource configmaps/service-props is missing the 
kubectl.kubernetes.io/last-applied-configuration annotation which is required 
by kubectl apply. kubectl apply should only be used on resources created 
declaratively by either kubectl create --save-config or kubectl apply. The 
missing annotation will be patched automatically.
+               //This is tracked here: 
https://issues.redhat.com/browse/KOGITO-9391 and it will be fixed by
+               //https://issues.redhat.com/browse/KOGITO-9381
+               if !strings.Contains(line, 
"kubectl.kubernetes.io/last-applied-configuration") {
+                       fmt.Fprintln(os.Stderr, line)
+               }
+       }
+       if err != nil {
+               fmt.Printf("has a error")
+               return fmt.Errorf("❌ ERROR: failed to execute kubectl apply 
command for %s: %s", crd, err)
+       }
+
+       return nil
+}
+
+func (m KubeCtl) ExecuteKubectlDelete(crd, namespace string) error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl",
+               "delete",
+               "-f", crd,
+               "-n", namespace)
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+
+       err := cmd.Run()
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: failed to execute kubectl delete 
command for %s: %s", crd, err)
+       }
+
+       return nil
+}
+
+func (m KubeCtl) CheckKubectlCrdExists(crd string) (bool, error) {
+       cmd := exec.Command("kubectl", "get", "crd", crd)
+       _, err := cmd.Output()
+       if err != nil {
+               return false, err
+       }
+       return true, nil
+}
+
+func CheckOperatorInstalled() error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl", "get", "pods", "-n", 
metadata.OperatorName)

Review Comment:
   You should use the Pod API instead, see an example here: 
https://github.com/kubernetes/client-go/blob/master/examples/out-of-cluster-client-configuration/main.go#L74
   
   Any references to `exec.Command` must be gone.



##########
packages/kn-plugin-workflow/pkg/common/k8sclient/goapi.go:
##########
@@ -0,0 +1,192 @@
+package k8sclient
+
+import (
+       "context"
+       "fmt"
+       "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+       "os"
+       "path/filepath"
+
+       "k8s.io/apimachinery/pkg/api/meta"
+       metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+       "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+       "k8s.io/apimachinery/pkg/runtime"
+       "k8s.io/apimachinery/pkg/util/yaml"
+
+       "k8s.io/client-go/dynamic"
+       "k8s.io/client-go/kubernetes/scheme"
+       "k8s.io/client-go/rest"
+       "k8s.io/client-go/tools/clientcmd"
+       "k8s.io/client-go/tools/clientcmd/api"
+)
+
+type GoAPI struct{}
+
+func KubeApiConfig() (*api.Config, error) {
+       homeDir, err := os.UserHomeDir()
+       if err != nil {
+               return nil, fmt.Errorf("error getting user home dir: %w", err)
+       }
+       kubeConfigPath := filepath.Join(homeDir, ".kube", "config")
+       fmt.Printf("🔎 Using kubeconfig: %s\n", kubeConfigPath)
+       config, err := clientcmd.LoadFromFile(kubeConfigPath)
+       if err != nil {
+               return nil, fmt.Errorf("❌ ERROR: Failed to load kubeconfig: 
%w", err)
+       }
+       return config, nil
+}
+
+func KubeRestConfig() (*rest.Config, error) {
+       config, err := rest.InClusterConfig()
+       if err != nil {
+               homeDir, err := os.UserHomeDir()
+               if err != nil {
+                       return nil, fmt.Errorf("error getting user home dir: 
%w", err)
+               }
+               kubeConfigPath := filepath.Join(homeDir, ".kube", "config")
+               fmt.Printf("🔎 Using kubeconfig: %s\n", kubeConfigPath)
+               config, err = clientcmd.BuildConfigFromFlags("", kubeConfigPath)
+               if err != nil {
+                       return nil, fmt.Errorf("❌ ERROR: Failed to load 
kubeconfig: %w", err)
+               }
+       }
+       return config, nil
+}
+
+func (m GoAPI) GetKubectlNamespace() (string, error) {
+       fmt.Println("🔎 Checking current namespace in kubectl...")
+
+       config, err := KubeApiConfig()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: Failed to get current kubectl 
namespace: %w", err)
+       }
+       namespace := config.Contexts[config.CurrentContext].Namespace
+
+       if len(namespace) == 0 {
+               namespace = "default"
+       }
+       fmt.Printf(" - ✅  kubectl current namespace: %s\n", namespace)
+       return namespace, nil
+}
+
+func (m GoAPI) CheckKubectlContext() (string, error) {
+       config, err := KubeApiConfig()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found %w", err)
+       }
+       context := config.CurrentContext
+       if context == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found")
+       }
+       fmt.Printf(" - ✅ kubectl current context: %s\n", context)
+       return context, nil
+}
+
+func (m GoAPI) ExecuteKubectlApply(path, namespace string) error {
+       config, err := KubeRestConfig()
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to create rest config for 
Kubernetes client: %v", err)
+       }
+
+       client, err := dynamic.NewForConfig(config)
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: Failed to create dynamic Kubernetes 
client: %v", err)
+       }

Review Comment:
   Maybe we should isolate this part of the codebase, it seems very similar to 
the other methods.



##########
packages/kn-plugin-workflow/pkg/common/k8sclient/kubectl.go:
##########
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package k8sclient
+
+import (
+       "bufio"
+       "bytes"
+       "fmt"
+       
"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata"
+       "os"
+       "os/exec"
+       "strings"
+)
+
+type KubeCtl struct{}
+
+func (m KubeCtl) GetKubectlNamespace() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+
+       fmt.Println("🔎 Checking current namespace in kubectl...")
+       cmd := exec.Command("kubectl", "config", "view", "--minify", 
"--output", "jsonpath={..namespace}")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: Failed to get current kubectl 
namespace: %w", err)
+       }
+       namespace := strings.TrimSpace(string(output))
+       if namespace == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl namespace 
found")
+       }
+       fmt.Printf(" - ✅  kubectl current namespace: %s\n", namespace)
+       return namespace, nil
+}
+
+func (m KubeCtl) CheckKubectlContext() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+       fmt.Println("🔎 Checking if kubectl has a context configured...")
+       cmd := exec.Command("kubectl", "config", "current-context")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found %w", err)
+       }
+       context := strings.TrimSpace(string(output))
+       if context == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found")
+       }
+       fmt.Printf(" - ✅ kubectl current context: %s \n", context)
+       return context, nil
+}
+
+func CheckKubectl() error {
+       fmt.Println("🔎 Checking if kubectl is available...")
+       _, kubectlCheck := exec.LookPath("kubectl")

Review Comment:
   Why do we need kubectl installed? To read the cluster's configuration?



##########
packages/kn-plugin-workflow/pkg/common/k8sclient/kubectl.go:
##########
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package k8sclient
+
+import (
+       "bufio"
+       "bytes"
+       "fmt"
+       
"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata"
+       "os"
+       "os/exec"
+       "strings"
+)
+
+type KubeCtl struct{}
+
+func (m KubeCtl) GetKubectlNamespace() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+
+       fmt.Println("🔎 Checking current namespace in kubectl...")
+       cmd := exec.Command("kubectl", "config", "view", "--minify", 
"--output", "jsonpath={..namespace}")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: Failed to get current kubectl 
namespace: %w", err)
+       }
+       namespace := strings.TrimSpace(string(output))
+       if namespace == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl namespace 
found")
+       }
+       fmt.Printf(" - ✅  kubectl current namespace: %s\n", namespace)
+       return namespace, nil
+}
+
+func (m KubeCtl) CheckKubectlContext() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+       fmt.Println("🔎 Checking if kubectl has a context configured...")
+       cmd := exec.Command("kubectl", "config", "current-context")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found %w", err)
+       }
+       context := strings.TrimSpace(string(output))
+       if context == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found")
+       }
+       fmt.Printf(" - ✅ kubectl current context: %s \n", context)
+       return context, nil
+}
+
+func CheckKubectl() error {
+       fmt.Println("🔎 Checking if kubectl is available...")
+       _, kubectlCheck := exec.LookPath("kubectl")
+       if err := kubectlCheck; err != nil {
+               fmt.Println("ERROR: kubectl not found")
+               fmt.Println("kubectl is required for deploy")
+               fmt.Println("Download it from 
https://kubectl.docs.kubernetes.io/installation/kubectl/";)
+               return fmt.Errorf("❌ ERROR: kubectl not found %w", err)
+       }
+
+       fmt.Println(" - ✅ kubectl is available")
+       return nil
+}
+
+func (m KubeCtl) ExecuteKubectlApply(crd, namespace string) error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl",
+               "apply",
+               "-f", crd,
+               "-n", namespace,
+               "--validate=false")
+
+       var stderror bytes.Buffer
+
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = &stderror //os.Stderr
+
+       err := cmd.Run()
+       scanner := bufio.NewScanner(&stderror)
+       for scanner.Scan() {
+               line := scanner.Text()
+               //Temporarily removing the following warning:
+               //In this context, using apply or create are interchangeable, 
but generates a warning.
+               //Warning: resource configmaps/service-props is missing the 
kubectl.kubernetes.io/last-applied-configuration annotation which is required 
by kubectl apply. kubectl apply should only be used on resources created 
declaratively by either kubectl create --save-config or kubectl apply. The 
missing annotation will be patched automatically.
+               //This is tracked here: 
https://issues.redhat.com/browse/KOGITO-9391 and it will be fixed by
+               //https://issues.redhat.com/browse/KOGITO-9381
+               if !strings.Contains(line, 
"kubectl.kubernetes.io/last-applied-configuration") {
+                       fmt.Fprintln(os.Stderr, line)
+               }
+       }
+       if err != nil {
+               fmt.Printf("has a error")
+               return fmt.Errorf("❌ ERROR: failed to execute kubectl apply 
command for %s: %s", crd, err)
+       }
+
+       return nil
+}
+
+func (m KubeCtl) ExecuteKubectlDelete(crd, namespace string) error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl",
+               "delete",
+               "-f", crd,
+               "-n", namespace)

Review Comment:
   Here we also should refactor to delete the objects directly from the REST 
Api.



##########
packages/kn-plugin-workflow/pkg/common/k8sclient/kubectl.go:
##########
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package k8sclient
+
+import (
+       "bufio"
+       "bytes"
+       "fmt"
+       
"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata"
+       "os"
+       "os/exec"
+       "strings"
+)
+
+type KubeCtl struct{}
+
+func (m KubeCtl) GetKubectlNamespace() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+
+       fmt.Println("🔎 Checking current namespace in kubectl...")
+       cmd := exec.Command("kubectl", "config", "view", "--minify", 
"--output", "jsonpath={..namespace}")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: Failed to get current kubectl 
namespace: %w", err)
+       }
+       namespace := strings.TrimSpace(string(output))
+       if namespace == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl namespace 
found")
+       }
+       fmt.Printf(" - ✅  kubectl current namespace: %s\n", namespace)
+       return namespace, nil
+}
+
+func (m KubeCtl) CheckKubectlContext() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+       fmt.Println("🔎 Checking if kubectl has a context configured...")
+       cmd := exec.Command("kubectl", "config", "current-context")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found %w", err)
+       }
+       context := strings.TrimSpace(string(output))
+       if context == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found")
+       }
+       fmt.Printf(" - ✅ kubectl current context: %s \n", context)
+       return context, nil
+}
+
+func CheckKubectl() error {
+       fmt.Println("🔎 Checking if kubectl is available...")
+       _, kubectlCheck := exec.LookPath("kubectl")
+       if err := kubectlCheck; err != nil {
+               fmt.Println("ERROR: kubectl not found")
+               fmt.Println("kubectl is required for deploy")
+               fmt.Println("Download it from 
https://kubectl.docs.kubernetes.io/installation/kubectl/";)
+               return fmt.Errorf("❌ ERROR: kubectl not found %w", err)
+       }
+
+       fmt.Println(" - ✅ kubectl is available")
+       return nil
+}
+
+func (m KubeCtl) ExecuteKubectlApply(crd, namespace string) error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl",
+               "apply",
+               "-f", crd,
+               "-n", namespace,
+               "--validate=false")

Review Comment:
   Handling the kubectl `last-applied-configuration` is unnecessary if we use 
the Rest clients instead.



##########
packages/kn-plugin-workflow/pkg/common/k8sclient/kubectl.go:
##########
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package k8sclient
+
+import (
+       "bufio"
+       "bytes"
+       "fmt"
+       
"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata"
+       "os"
+       "os/exec"
+       "strings"
+)
+
+type KubeCtl struct{}
+
+func (m KubeCtl) GetKubectlNamespace() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+
+       fmt.Println("🔎 Checking current namespace in kubectl...")
+       cmd := exec.Command("kubectl", "config", "view", "--minify", 
"--output", "jsonpath={..namespace}")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: Failed to get current kubectl 
namespace: %w", err)
+       }
+       namespace := strings.TrimSpace(string(output))
+       if namespace == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl namespace 
found")
+       }
+       fmt.Printf(" - ✅  kubectl current namespace: %s\n", namespace)
+       return namespace, nil
+}
+
+func (m KubeCtl) CheckKubectlContext() (string, error) {
+       if err := CheckKubectl(); err != nil {
+               return "", err
+       }
+       fmt.Println("🔎 Checking if kubectl has a context configured...")
+       cmd := exec.Command("kubectl", "config", "current-context")
+       output, err := cmd.Output()
+       if err != nil {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found %w", err)
+       }
+       context := strings.TrimSpace(string(output))
+       if context == "" {
+               return "", fmt.Errorf("❌ ERROR: No current kubectl context 
found")
+       }
+       fmt.Printf(" - ✅ kubectl current context: %s \n", context)
+       return context, nil
+}
+
+func CheckKubectl() error {
+       fmt.Println("🔎 Checking if kubectl is available...")
+       _, kubectlCheck := exec.LookPath("kubectl")
+       if err := kubectlCheck; err != nil {
+               fmt.Println("ERROR: kubectl not found")
+               fmt.Println("kubectl is required for deploy")
+               fmt.Println("Download it from 
https://kubectl.docs.kubernetes.io/installation/kubectl/";)
+               return fmt.Errorf("❌ ERROR: kubectl not found %w", err)
+       }
+
+       fmt.Println(" - ✅ kubectl is available")
+       return nil
+}
+
+func (m KubeCtl) ExecuteKubectlApply(crd, namespace string) error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl",
+               "apply",
+               "-f", crd,
+               "-n", namespace,
+               "--validate=false")
+
+       var stderror bytes.Buffer
+
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = &stderror //os.Stderr
+
+       err := cmd.Run()
+       scanner := bufio.NewScanner(&stderror)
+       for scanner.Scan() {
+               line := scanner.Text()
+               //Temporarily removing the following warning:
+               //In this context, using apply or create are interchangeable, 
but generates a warning.
+               //Warning: resource configmaps/service-props is missing the 
kubectl.kubernetes.io/last-applied-configuration annotation which is required 
by kubectl apply. kubectl apply should only be used on resources created 
declaratively by either kubectl create --save-config or kubectl apply. The 
missing annotation will be patched automatically.
+               //This is tracked here: 
https://issues.redhat.com/browse/KOGITO-9391 and it will be fixed by
+               //https://issues.redhat.com/browse/KOGITO-9381
+               if !strings.Contains(line, 
"kubectl.kubernetes.io/last-applied-configuration") {
+                       fmt.Fprintln(os.Stderr, line)
+               }
+       }
+       if err != nil {
+               fmt.Printf("has a error")
+               return fmt.Errorf("❌ ERROR: failed to execute kubectl apply 
command for %s: %s", crd, err)
+       }
+
+       return nil
+}
+
+func (m KubeCtl) ExecuteKubectlDelete(crd, namespace string) error {
+       if err := CheckKubectl(); err != nil {
+               return err
+       }
+       cmd := exec.Command("kubectl",
+               "delete",
+               "-f", crd,
+               "-n", namespace)
+       cmd.Stdout = os.Stdout
+       cmd.Stderr = os.Stderr
+
+       err := cmd.Run()
+       if err != nil {
+               return fmt.Errorf("❌ ERROR: failed to execute kubectl delete 
command for %s: %s", crd, err)
+       }
+
+       return nil
+}
+
+func (m KubeCtl) CheckKubectlCrdExists(crd string) (bool, error) {
+       cmd := exec.Command("kubectl", "get", "crd", crd)

Review Comment:
   Same here regarding the usage of `kubectl`.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to