github.com/swaros/contxt/module/taskrun@v0.0.0-20240305083542-3dbd4436ac40/checker.go (about)

     1  // Copyright (c) 2020 Thomas Ziegler <thomas.zglr@googlemail.com>. All rights reserved.
     2  //
     3  // Licensed under the MIT License
     4  //
     5  //
     6  // Permission is hereby granted, free of charge, to any person obtaining a copy
     7  // of this software and associated documentation files (the "Software"), to deal
     8  // in the Software without restriction, including without limitation the rights
     9  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    10  // copies of the Software, and to permit persons to whom the Software is
    11  // furnished to do so, subject to the following conditions:
    12  //
    13  // The above copyright notice and this permission notice shall be included in all
    14  // copies or substantial portions of the Software.
    15  //
    16  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    17  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    18  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    19  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    20  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    21  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    22  // SOFTWARE.
    23  
    24  package taskrun
    25  
    26  import (
    27  	"fmt"
    28  	"os"
    29  	"strings"
    30  
    31  	"github.com/sirupsen/logrus"
    32  	"github.com/swaros/contxt/module/configure"
    33  	"github.com/swaros/contxt/module/dirhandle"
    34  )
    35  
    36  // test all requirements
    37  // - operation system
    38  // - variable matches
    39  // - files exists
    40  // - files not exists
    41  // - environment variables
    42  // returns bool and the message what is checked.
    43  func checkRequirements(require configure.Require) (bool, string) {
    44  
    45  	// check operating system
    46  	if require.System != "" {
    47  		match := StringMatchTest(require.System, configure.GetOs())
    48  		if !match {
    49  			return false, "operating system '" + configure.GetOs() + "' is not matching with '" + require.System + "'"
    50  		}
    51  	}
    52  
    53  	// check file exists
    54  	for _, fileExists := range require.Exists {
    55  		fileExists = HandlePlaceHolder(fileExists)
    56  		fexists, err := dirhandle.Exists(fileExists)
    57  		GetLogger().WithFields(logrus.Fields{
    58  			"path":   fileExists,
    59  			"result": fexists,
    60  		}).Debug("path exists? result=true means valid for require")
    61  		if err != nil || !fexists {
    62  
    63  			return false, "required file (" + fileExists + ") not found "
    64  		}
    65  	}
    66  
    67  	// check file not exists
    68  	for _, fileNotExists := range require.NotExists {
    69  		fileNotExists = HandlePlaceHolder(fileNotExists)
    70  		fexists, err := dirhandle.Exists(fileNotExists)
    71  		GetLogger().WithFields(logrus.Fields{
    72  			"path":   fileNotExists,
    73  			"result": fexists,
    74  		}).Debug("path NOT exists? result=true means not valid for require")
    75  		if err != nil || fexists {
    76  			return false, "unexpected file (" + fileNotExists + ")  found "
    77  		}
    78  	}
    79  
    80  	// check environment variable is set
    81  	for name, pattern := range require.Environment {
    82  		envVar, envExists := os.LookupEnv(name)
    83  		if !envExists || !StringMatchTest(pattern, envVar) {
    84  			if envExists {
    85  				return false, "environment variable[" + name + "] not matching with " + pattern
    86  			}
    87  			return false, "environment variable[" + name + "] not exists"
    88  		}
    89  	}
    90  
    91  	// check variables
    92  	for name, pattern := range require.Variables {
    93  		defVar, defExists := GetPHExists(name)
    94  		if !defExists || !StringMatchTest(pattern, defVar) {
    95  			if defExists {
    96  				return false, "runtime variable[" + name + "] not matching with " + pattern
    97  			}
    98  			return false, "runtime variable[" + name + "] not exists "
    99  		}
   100  	}
   101  
   102  	return true, ""
   103  }
   104  
   105  // StringMatchTest test a pattern and a value.
   106  // in this example: myvar: "=hello"
   107  // the patter is "=hello" and the value should be "hello" for a match
   108  func StringMatchTest(pattern, value string) bool {
   109  	first := pattern
   110  	maybeMatch := value
   111  	if len(pattern) > 1 {
   112  		maybeMatch = pattern[1:]
   113  		first = pattern[0:1]
   114  	}
   115  	switch first {
   116  	// string not empty
   117  	case "?":
   118  		GetLogger().WithFields(logrus.Fields{"pattern": pattern, "value": value, "check": first, "result": (value != "")}).Debug("check anything then empty")
   119  		return (value != "")
   120  
   121  	// string equals
   122  	case "=":
   123  		GetLogger().WithFields(logrus.Fields{"pattern": maybeMatch, "value": value, "check": first, "result": (maybeMatch == value)}).Debug("check equal")
   124  		return (maybeMatch == value)
   125  
   126  	// string not equals
   127  	case "!":
   128  		GetLogger().WithFields(logrus.Fields{"pattern": maybeMatch, "value": value, "check": first, "result": (maybeMatch != value)}).Debug("check not equal")
   129  		return (maybeMatch != value)
   130  
   131  	// string greater
   132  	case ">":
   133  		GetLogger().WithFields(logrus.Fields{"pattern": maybeMatch, "value": value, "check": first, "result": (maybeMatch < value)}).Debug("check greather then")
   134  		return (value > maybeMatch)
   135  
   136  	// sstring lower
   137  	case "<":
   138  		GetLogger().WithFields(logrus.Fields{"pattern": maybeMatch, "value": value, "check": first, "result": (maybeMatch > value)}).Debug("check lower then")
   139  		return (value < maybeMatch)
   140  
   141  	// string not empty
   142  	case "*":
   143  		GetLogger().WithFields(logrus.Fields{"pattern": maybeMatch, "value": value, "check": first, "result": (value != "")}).Debug("check empty *")
   144  		return (value != "")
   145  
   146  	// default is checking equals
   147  	default:
   148  		GetLogger().WithFields(logrus.Fields{"pattern": pattern, "value": value, "check": first, "result": (pattern == value)}).Debug("default: check equal against plain values")
   149  		return (pattern == value)
   150  	}
   151  }
   152  
   153  // checks reasons that is used for some triggers
   154  // retunrs bool and a message what trigger was matched and the reason
   155  func checkReason(checkReason configure.Trigger, output string, e error) (bool, string) {
   156  	GetLogger().WithFields(logrus.Fields{
   157  		"contains":   checkReason.OnoutContains,
   158  		"onError":    checkReason.Onerror,
   159  		"onLess":     checkReason.OnoutcountLess,
   160  		"onMore":     checkReason.OnoutcountMore,
   161  		"testing-at": output,
   162  	}).Debug("Checking Trigger")
   163  
   164  	var message = ""
   165  	// now means forcing this trigger
   166  	if checkReason.Now {
   167  		message = "reason now match always"
   168  		return true, message
   169  	}
   170  	// checks a error happens
   171  	if checkReason.Onerror && e != nil {
   172  		message = fmt.Sprint("reason match because a error happen (", e, ")  ")
   173  		return true, message
   174  	}
   175  
   176  	// checks if the output from comand contains les then X chars
   177  	if checkReason.OnoutcountLess > 0 && checkReason.OnoutcountLess > len(output) {
   178  		message = fmt.Sprint("reason match output len (", len(output), ") is less then ", checkReason.OnoutcountLess)
   179  		return true, message
   180  	}
   181  	// checks if the output contains more then X chars
   182  	if checkReason.OnoutcountMore > 0 && checkReason.OnoutcountMore < len(output) {
   183  		message = fmt.Sprint("reason match output len (", len(output), ") is more then ", checkReason.OnoutcountMore)
   184  		return true, message
   185  	}
   186  
   187  	// checks if the output contains one of the defined text-lines
   188  	for _, checkText := range checkReason.OnoutContains {
   189  		checkText = HandlePlaceHolder(checkText)
   190  		if checkText != "" && strings.Contains(output, checkText) {
   191  			message = fmt.Sprint("reason match because output contains ", checkText)
   192  			return true, message
   193  		}
   194  		if checkText != "" {
   195  			GetLogger().WithFields(logrus.Fields{
   196  				"check": checkText,
   197  				"with":  output,
   198  				"from":  checkReason.OnoutContains,
   199  			}).Debug("OnoutContains NO MATCH")
   200  		}
   201  	}
   202  
   203  	return false, message
   204  }