github.com/uhthomas/helm@v3.0.0-beta.3+incompatible/pkg/action/lint.go (about)

     1  /*
     2  Copyright The Helm Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package action
    18  
    19  import (
    20  	"io/ioutil"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  
    25  	"github.com/pkg/errors"
    26  
    27  	"helm.sh/helm/pkg/chartutil"
    28  	"helm.sh/helm/pkg/lint"
    29  	"helm.sh/helm/pkg/lint/support"
    30  )
    31  
    32  var errLintNoChart = errors.New("no chart found for linting (missing Chart.yaml)")
    33  
    34  // Lint is the action for checking that the semantics of a chart are well-formed.
    35  //
    36  // It provides the implementation of 'helm lint'.
    37  type Lint struct {
    38  	Strict    bool
    39  	Namespace string
    40  }
    41  
    42  type LintResult struct {
    43  	TotalChartsLinted int
    44  	Messages          []support.Message
    45  	Errors            []error
    46  }
    47  
    48  // NewLint creates a new Lint object with the given configuration.
    49  func NewLint() *Lint {
    50  	return &Lint{}
    51  }
    52  
    53  // Run executes 'helm Lint' against the given chart.
    54  func (l *Lint) Run(paths []string, vals map[string]interface{}) *LintResult {
    55  	lowestTolerance := support.ErrorSev
    56  	if l.Strict {
    57  		lowestTolerance = support.WarningSev
    58  	}
    59  
    60  	result := &LintResult{}
    61  	for _, path := range paths {
    62  		linter, err := lintChart(path, vals, l.Namespace, l.Strict)
    63  		if err != nil {
    64  			if err == errLintNoChart {
    65  				result.Errors = append(result.Errors, err)
    66  			}
    67  			if linter.HighestSeverity >= lowestTolerance {
    68  				result.Errors = append(result.Errors, err)
    69  			}
    70  		} else {
    71  			result.Messages = append(result.Messages, linter.Messages...)
    72  			result.TotalChartsLinted++
    73  			for _, msg := range linter.Messages {
    74  				if msg.Severity == support.ErrorSev {
    75  					result.Errors = append(result.Errors, msg.Err)
    76  				}
    77  			}
    78  		}
    79  	}
    80  	return result
    81  }
    82  
    83  func lintChart(path string, vals map[string]interface{}, namespace string, strict bool) (support.Linter, error) {
    84  	var chartPath string
    85  	linter := support.Linter{}
    86  	currentVals := make(map[string]interface{}, len(vals))
    87  	for key, value := range vals {
    88  		currentVals[key] = value
    89  	}
    90  
    91  	if strings.HasSuffix(path, ".tgz") {
    92  		tempDir, err := ioutil.TempDir("", "helm-lint")
    93  		if err != nil {
    94  			return linter, err
    95  		}
    96  		defer os.RemoveAll(tempDir)
    97  
    98  		file, err := os.Open(path)
    99  		if err != nil {
   100  			return linter, err
   101  		}
   102  		defer file.Close()
   103  
   104  		if err = chartutil.Expand(tempDir, file); err != nil {
   105  			return linter, err
   106  		}
   107  
   108  		lastHyphenIndex := strings.LastIndex(filepath.Base(path), "-")
   109  		if lastHyphenIndex <= 0 {
   110  			return linter, errors.Errorf("unable to parse chart archive %q, missing '-'", filepath.Base(path))
   111  		}
   112  		base := filepath.Base(path)[:lastHyphenIndex]
   113  		chartPath = filepath.Join(tempDir, base)
   114  	} else {
   115  		chartPath = path
   116  	}
   117  
   118  	// Guard: Error out of this is not a chart.
   119  	if _, err := os.Stat(filepath.Join(chartPath, "Chart.yaml")); err != nil {
   120  		return linter, errLintNoChart
   121  	}
   122  
   123  	return lint.All(chartPath, currentVals, namespace, strict), nil
   124  }