github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow@v0.28.1-0.20240311201729-34c6856b157f/pkg/common/operator.go (about)

     1  /*
     2   * Licensed to the Apache Software Foundation (ASF) under one
     3   * or more contributor license agreements.  See the NOTICE file
     4   * distributed with this work for additional information
     5   * regarding copyright ownership.  The ASF licenses this file
     6   * to you under the Apache License, Version 2.0 (the
     7   * "License"); you may not use this file except in compliance
     8   * with the License.  You may obtain a copy of the License at
     9   *
    10   *  http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing,
    13   * software distributed under the License is distributed on an
    14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   * KIND, either express or implied.  See the License for the
    16   * specific language governing permissions and limitations
    17   * under the License.
    18   */
    19  
    20  package common
    21  
    22  import (
    23  	"bufio"
    24  	"bytes"
    25  	"fmt"
    26  	"github.com/apache/incubator-kie-tools/packages/kn-plugin-workflow/pkg/metadata"
    27  	"gopkg.in/yaml.v2"
    28  	"io"
    29  	"os"
    30  	"os/exec"
    31  	"path/filepath"
    32  	"strings"
    33  )
    34  
    35  type Document struct {
    36  	Kind string `yaml:"kind"`
    37  }
    38  
    39  func ExecuteKubectlApply(crd, namespace string) error {
    40  
    41  	cmd := exec.Command("kubectl",
    42  		"apply",
    43  		"-f", crd,
    44  		"-n", namespace,
    45  		"--validate=false")
    46  
    47  	var stderror bytes.Buffer
    48  
    49  	cmd.Stdout = os.Stdout
    50  	cmd.Stderr = &stderror //os.Stderr
    51  
    52  	err := cmd.Run()
    53  	scanner := bufio.NewScanner(&stderror)
    54  	for scanner.Scan() {
    55  		line := scanner.Text()
    56  		//Temporarily removing the following warning:
    57  		//In this context, using apply or create are interchangeable, but generates a warning.
    58  		//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.
    59  		//This is tracked here: https://issues.redhat.com/browse/KOGITO-9391 and it will be fixed by
    60  		//https://issues.redhat.com/browse/KOGITO-9381
    61  		if !strings.Contains(line, "kubectl.kubernetes.io/last-applied-configuration") {
    62  			fmt.Fprintln(os.Stderr, line)
    63  		}
    64  	}
    65  	if err != nil {
    66  		fmt.Printf("has a error")
    67  		return fmt.Errorf("❌ ERROR: failed to execute kubectl apply command for %s: %s", crd, err)
    68  	}
    69  
    70  	return nil
    71  }
    72  
    73  func ExecuteKubectlDelete(crd, namespace string) error {
    74  
    75  	cmd := exec.Command("kubectl",
    76  		"delete",
    77  		"-f", crd,
    78  		"-n", namespace)
    79  	cmd.Stdout = os.Stdout
    80  	cmd.Stderr = os.Stderr
    81  
    82  	err := cmd.Run()
    83  	if err != nil {
    84  		return fmt.Errorf("❌ ERROR: failed to execute kubectl delete command for %s: %s", crd, err)
    85  	}
    86  
    87  	return nil
    88  }
    89  
    90  func CheckOperatorInstalled() error {
    91  	cmd := exec.Command("kubectl", "get", "pods", "-n", metadata.OperatorName)
    92  
    93  	output, err := cmd.Output()
    94  	if err != nil {
    95  		return fmt.Errorf("❌ ERROR: SonataFlow Operator not found %w", err)
    96  	}
    97  
    98  	// Check if the pod is running
    99  	operatorRunning := checkOperatorRunning(string(output))
   100  	if !operatorRunning {
   101  		return fmt.Errorf("❌ ERROR: SonataFlow Operator not found")
   102  	}
   103  
   104  	fmt.Println(" - ✅ SonataFlow Operator is available")
   105  	return nil
   106  }
   107  
   108  func checkOperatorRunning(getPodsOutPut string) bool {
   109  	pods := strings.Split(getPodsOutPut, "\n")
   110  	for _, pod := range pods {
   111  		// Split each line into fields (NAME, READY, STATUS, RESTARTS, AGE)
   112  		fields := strings.Fields(pod)
   113  
   114  		// Check if this line contains information about the desired operator manager pod
   115  		if len(fields) > 2 && strings.HasPrefix(fields[0], metadata.OperatorManagerPod) && fields[2] == "Running" {
   116  			return true
   117  		}
   118  	}
   119  	return false
   120  }
   121  
   122  func FindServiceFiles(directory string) ([]string, error) {
   123  	var serviceFiles []string
   124  
   125  	err := filepath.Walk(directory, func(path string, info os.FileInfo, err error) error {
   126  		if err != nil {
   127  			return fmt.Errorf("❌ ERROR: failure accessing a path %q: %v\n", path, err)
   128  		}
   129  
   130  		if info.IsDir() || filepath.Ext(path) != ".yaml" {
   131  			return nil
   132  		}
   133  
   134  		file, err := os.Open(path)
   135  		if err != nil {
   136  			return fmt.Errorf("❌ ERROR: failure opening file %q: %v\n", path, err)
   137  		}
   138  		defer file.Close()
   139  
   140  		byteValue, err := io.ReadAll(file)
   141  		if err != nil {
   142  			return fmt.Errorf("❌ ERROR: failure reading file %q: %v\n", path, err)
   143  		}
   144  
   145  		var doc Document
   146  		if err := yaml.Unmarshal(byteValue, &doc); err != nil {
   147  			return fmt.Errorf("❌ ERROR: failure unmarshalling YAML from file %q: %v\n", path, err)
   148  		}
   149  
   150  		if doc.Kind == metadata.ManifestServiceFilesKind {
   151  			serviceFiles = append(serviceFiles, path)
   152  		}
   153  
   154  		return nil
   155  	})
   156  
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  
   161  	return serviceFiles, nil
   162  }