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]