mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
d29ba346f2
* modify wrapper http to hold ca rot * modifying the http client for maven build * adding checks * eliminating seperate jks * test tls true * insecure flag remove * error debug * storing cert * sap root cert * error * only child cert * test * maven test * moving outside loop * changing pointer * dont download existing certs * typo fix * removing mavenBuild test * code clean up * making hadolint using always cert true * custom tls link for hadolint trust * error handel * extended condition for modifying custom tls * unit test case * checing when to add the customLinks * not breaking existing hadolint client config Co-authored-by: Your Name <you@example.com>
133 lines
4.4 KiB
Go
133 lines
4.4 KiB
Go
package cmd
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"time"
|
|
|
|
"github.com/SAP/jenkins-library/pkg/command"
|
|
piperhttp "github.com/SAP/jenkins-library/pkg/http"
|
|
"github.com/SAP/jenkins-library/pkg/log"
|
|
"github.com/SAP/jenkins-library/pkg/piperutils"
|
|
"github.com/SAP/jenkins-library/pkg/telemetry"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const hadolintCommand = "hadolint"
|
|
|
|
// HadolintPiperFileUtils abstracts piperutils.Files
|
|
// mock generated with: mockery --name HadolintPiperFileUtils --dir cmd --output pkg/hadolint/mocks
|
|
type HadolintPiperFileUtils interface {
|
|
FileExists(filename string) (bool, error)
|
|
FileWrite(filename string, data []byte, perm os.FileMode) error
|
|
}
|
|
|
|
// HadolintClient abstracts http.Client
|
|
// mock generated with: mockery --name hadolintClient --dir cmd --output pkg/hadolint/mocks
|
|
type HadolintClient interface {
|
|
SetOptions(options piperhttp.ClientOptions)
|
|
DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error
|
|
}
|
|
|
|
// hadolintRunner abstracts command.Command
|
|
type hadolintRunner interface {
|
|
RunExecutable(executable string, params ...string) error
|
|
Stdout(err io.Writer)
|
|
Stderr(err io.Writer)
|
|
}
|
|
|
|
type hadolintUtils struct {
|
|
HadolintPiperFileUtils
|
|
HadolintClient
|
|
hadolintRunner
|
|
}
|
|
|
|
func hadolintExecute(config hadolintExecuteOptions, _ *telemetry.CustomData) {
|
|
runner := command.Command{
|
|
ErrorCategoryMapping: map[string][]string{},
|
|
}
|
|
// reroute runner output to logging framework
|
|
runner.Stdout(log.Writer())
|
|
runner.Stderr(log.Writer())
|
|
|
|
utils := hadolintUtils{
|
|
HadolintPiperFileUtils: &piperutils.Files{},
|
|
HadolintClient: &piperhttp.Client{},
|
|
hadolintRunner: &runner,
|
|
}
|
|
|
|
if err := runHadolint(config, utils); err != nil {
|
|
log.Entry().WithError(err).Fatal("Execution failed")
|
|
}
|
|
}
|
|
|
|
func runHadolint(config hadolintExecuteOptions, utils hadolintUtils) error {
|
|
var outputBuffer bytes.Buffer
|
|
var errorBuffer bytes.Buffer
|
|
utils.Stdout(&outputBuffer)
|
|
utils.Stderr(&errorBuffer)
|
|
|
|
options := []string{"--format", "checkstyle"}
|
|
// load config file from URL
|
|
if !hasConfigurationFile(config.ConfigurationFile, utils) && len(config.ConfigurationURL) > 0 {
|
|
clientOptions := piperhttp.ClientOptions{
|
|
TransportTimeout: 20 * time.Second,
|
|
TransportSkipVerification: true,
|
|
}
|
|
if len(config.CustomTLSCertificateLinks) > 0 {
|
|
clientOptions.TransportSkipVerification = false
|
|
clientOptions.TrustedCerts = config.CustomTLSCertificateLinks
|
|
}
|
|
|
|
if len(config.ConfigurationUsername) > 0 {
|
|
clientOptions.Username = config.ConfigurationUsername
|
|
clientOptions.Password = config.ConfigurationPassword
|
|
}
|
|
utils.SetOptions(clientOptions)
|
|
if err := loadConfigurationFile(config.ConfigurationURL, config.ConfigurationFile, utils); err != nil {
|
|
return errors.Wrap(err, "failed to load configuration file from URL")
|
|
}
|
|
}
|
|
// use config
|
|
if hasConfigurationFile(config.ConfigurationFile, utils) {
|
|
options = append(options, "--config", config.ConfigurationFile)
|
|
log.Entry().WithField("file", config.ConfigurationFile).Debug("Using configuration file")
|
|
} else {
|
|
log.Entry().Debug("No configuration file found.")
|
|
}
|
|
// execute scan command
|
|
err := utils.RunExecutable(hadolintCommand, append([]string{config.DockerFile}, options...)...)
|
|
|
|
//TODO: related to https://github.com/hadolint/hadolint/issues/391
|
|
// hadolint exists with 1 if there are processing issues but also if there are findings
|
|
// thus check stdout first if a report was created
|
|
if output := outputBuffer.String(); len(output) > 0 {
|
|
log.Entry().WithField("report", output).Debug("Report created")
|
|
utils.FileWrite(config.ReportFile, []byte(output), 0666)
|
|
} else if err != nil {
|
|
// if stdout is empty a processing issue occured
|
|
return errors.Wrap(err, errorBuffer.String())
|
|
}
|
|
//TODO: mock away in tests
|
|
// persist report information
|
|
piperutils.PersistReportsAndLinks("hadolintExecute", "./", []piperutils.Path{{Target: config.ReportFile}}, []piperutils.Path{})
|
|
return nil
|
|
}
|
|
|
|
// loadConfigurationFile loads a file from the provided url
|
|
func loadConfigurationFile(url, file string, utils hadolintUtils) error {
|
|
log.Entry().WithField("url", url).Debug("Loading configuration file from URL")
|
|
return utils.DownloadFile(url, file, nil, nil)
|
|
}
|
|
|
|
// hasConfigurationFile checks if the given file exists
|
|
func hasConfigurationFile(file string, utils hadolintUtils) bool {
|
|
exists, err := utils.FileExists(file)
|
|
if err != nil {
|
|
log.Entry().WithError(err).Error()
|
|
}
|
|
return exists
|
|
}
|