2020-03-06 03:00:18 +05:30
package apply
import (
2020-10-02 06:52:58 +05:30
"bufio"
2020-03-06 03:00:18 +05:30
"encoding/json"
"fmt"
2020-08-11 22:59:50 +05:30
"io/ioutil"
2020-06-08 17:01:56 +05:30
"os"
2020-07-21 00:41:30 +05:30
"path/filepath"
2020-10-15 17:29:07 -07:00
"reflect"
2020-07-21 00:41:30 +05:30
"strings"
2020-04-03 10:30:52 +05:30
"time"
2020-11-03 01:25:32 +05:30
"github.com/kyverno/kyverno/pkg/engine/response"
yaml1 "sigs.k8s.io/yaml"
2020-10-15 17:29:07 -07:00
v1 "github.com/kyverno/kyverno/pkg/api/kyverno/v1"
2020-10-07 11:12:31 -07:00
client "github.com/kyverno/kyverno/pkg/dclient"
2020-10-15 17:29:07 -07:00
"github.com/kyverno/kyverno/pkg/engine"
"github.com/kyverno/kyverno/pkg/engine/context"
2020-10-07 11:12:31 -07:00
"github.com/kyverno/kyverno/pkg/kyverno/common"
"github.com/kyverno/kyverno/pkg/kyverno/sanitizedError"
2020-10-15 17:29:07 -07:00
"github.com/kyverno/kyverno/pkg/openapi"
2020-10-07 11:12:31 -07:00
policy2 "github.com/kyverno/kyverno/pkg/policy"
2020-10-15 17:29:07 -07:00
"github.com/kyverno/kyverno/pkg/utils"
2020-03-06 03:00:18 +05:30
"github.com/spf13/cobra"
yamlv2 "gopkg.in/yaml.v2"
2020-10-15 17:29:07 -07:00
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/util/yaml"
2020-03-06 03:00:18 +05:30
"k8s.io/cli-runtime/pkg/genericclioptions"
2020-03-20 11:43:21 -07:00
log "sigs.k8s.io/controller-runtime/pkg/log"
2020-03-06 03:00:18 +05:30
)
2020-08-18 21:03:00 -07:00
type resultCounts struct {
2020-09-01 09:11:20 -07:00
pass int
fail int
warn int
2020-08-18 21:03:00 -07:00
error int
2020-09-01 09:11:20 -07:00
skip int
2020-08-18 21:03:00 -07:00
}
2020-10-30 16:38:19 +05:30
type Resource struct {
Name string ` json:"name" `
Values map [ string ] string ` json:"values" `
}
type Policy struct {
Name string ` json:"name" `
Resources [ ] Resource ` json:"resources" `
}
type Values struct {
Policies [ ] Policy ` json:"policies" `
}
2020-03-06 03:00:18 +05:30
func Command ( ) * cobra . Command {
var cmd * cobra . Command
var resourcePaths [ ] string
2020-10-21 20:05:05 +05:30
var cluster , policyReport bool
var mutateLogPath , variablesString , valuesFile , namespace string
2020-08-11 22:59:50 +05:30
2020-03-06 03:00:18 +05:30
kubernetesConfig := genericclioptions . NewConfigFlags ( true )
cmd = & cobra . Command {
Use : "apply" ,
2020-08-18 21:03:00 -07:00
Short : "applies policies on resources" ,
2020-03-06 03:00:18 +05:30
Example : fmt . Sprintf ( "To apply on a resource:\nkyverno apply /path/to/policy.yaml /path/to/folderOfPolicies --resource=/path/to/resource1 --resource=/path/to/resource2\n\nTo apply on a cluster\nkyverno apply /path/to/policy.yaml /path/to/folderOfPolicies --cluster" ) ,
RunE : func ( cmd * cobra . Command , policyPaths [ ] string ) ( err error ) {
defer func ( ) {
if err != nil {
if ! sanitizedError . IsErrorSanitized ( err ) {
2020-03-20 11:43:21 -07:00
log . Log . Error ( err , "failed to sanitize" )
2020-08-05 23:53:27 +05:30
err = fmt . Errorf ( "internal error" )
2020-03-06 03:00:18 +05:30
}
}
} ( )
2020-08-12 13:39:06 +05:30
if valuesFile != "" && variablesString != "" {
return sanitizedError . NewWithError ( "pass the values either using set flag or values_file flag" , err )
}
2020-10-30 16:38:19 +05:30
variables , valuesMap , err := getVariable ( variablesString , valuesFile )
if err != nil {
if ! sanitizedError . IsErrorSanitized ( err ) {
2020-08-12 13:39:06 +05:30
return sanitizedError . NewWithError ( "failed to decode yaml" , err )
2020-08-11 22:59:50 +05:30
}
2020-10-30 16:38:19 +05:30
return err
2020-08-11 22:59:50 +05:30
}
2020-10-16 19:56:32 +05:30
openAPIController , err := openapi . NewOpenAPIController ( )
if err != nil {
return sanitizedError . NewWithError ( "failed to initialize openAPIController" , err )
}
var dClient * client . Client
if cluster {
restConfig , err := kubernetesConfig . ToRESTConfig ( )
if err != nil {
return err
}
dClient , err = client . NewClient ( restConfig , 5 * time . Minute , make ( chan struct { } ) , log . Log )
if err != nil {
return err
2020-08-11 09:03:25 +05:30
}
2020-08-05 23:53:27 +05:30
}
2020-10-21 20:05:05 +05:30
if len ( policyPaths ) == 0 && ! cluster {
return sanitizedError . NewWithError ( fmt . Sprintf ( "policy file(s) or cluster required" ) , err )
}
2020-10-16 19:56:32 +05:30
2020-11-03 01:25:32 +05:30
policies , err := common . ValidateAndGetPolicies ( policyPaths )
2020-10-16 19:56:32 +05:30
if err != nil {
if ! sanitizedError . IsErrorSanitized ( err ) {
return sanitizedError . NewWithError ( "failed to mutate policies." , err )
}
return err
}
2020-03-06 03:00:18 +05:30
if len ( resourcePaths ) == 0 && ! cluster {
2020-08-18 21:03:00 -07:00
return sanitizedError . NewWithError ( fmt . Sprintf ( "resource file(s) or cluster required" ) , err )
2020-07-21 00:41:30 +05:30
}
2020-10-30 16:38:19 +05:30
mutateLogPathIsDir , err := checkMutateLogPath ( mutateLogPath )
if err != nil {
if ! sanitizedError . IsErrorSanitized ( err ) {
return sanitizedError . NewWithError ( "failed to create file/folder" , err )
2020-07-21 00:41:30 +05:30
}
2020-10-30 16:38:19 +05:30
return err
2020-03-06 03:00:18 +05:30
}
2020-11-03 01:25:32 +05:30
resources , err := getResourceAccordingToResourcePath ( resourcePaths , cluster , policies , dClient , namespace )
2020-10-30 16:38:19 +05:30
if err != nil {
if ! sanitizedError . IsErrorSanitized ( err ) {
2020-10-02 06:52:58 +05:30
return sanitizedError . NewWithError ( "failed to load resources" , err )
}
2020-10-30 16:38:19 +05:30
return err
}
2020-08-18 21:03:00 -07:00
mutatedPolicies , err := mutatePolices ( policies )
2020-10-21 20:05:05 +05:30
2020-08-18 21:03:00 -07:00
msgPolicies := "1 policy"
if len ( mutatedPolicies ) > 1 {
msgPolicies = fmt . Sprintf ( "%d policies" , len ( policies ) )
2020-07-10 14:56:07 +05:30
}
2020-08-18 21:03:00 -07:00
msgResources := "1 resource"
if len ( resources ) > 1 {
msgResources = fmt . Sprintf ( "%d resources" , len ( resources ) )
}
2020-10-21 20:05:05 +05:30
if len ( mutatedPolicies ) > 0 && len ( resources ) > 0 {
2020-10-30 16:38:19 +05:30
fmt . Printf ( "\napplying %s to %s... \n" , msgPolicies , msgResources )
2020-08-18 21:03:00 -07:00
}
rc := & resultCounts { }
2020-10-27 00:41:16 +05:30
engineResponses := make ( [ ] response . EngineResponse , 0 )
2020-08-18 21:03:00 -07:00
for _ , policy := range mutatedPolicies {
err := policy2 . Validate ( utils . MarshalPolicy ( * policy ) , nil , true , openAPIController )
if err != nil {
rc . skip += len ( resources )
fmt . Printf ( "\nskipping policy %v as it is not valid: %v\n" , policy . Name , err )
continue
}
2020-03-06 03:00:18 +05:30
2020-08-22 01:21:29 +05:30
if common . PolicyHasVariables ( * policy ) && variablesString == "" && valuesFile == "" {
2020-08-18 21:03:00 -07:00
rc . skip += len ( resources )
2020-08-22 01:21:29 +05:30
fmt . Printf ( "\nskipping policy %s as it has variables. pass the values for the variables using set/values_file flag" , policy . Name )
2020-08-18 21:03:00 -07:00
continue
}
2020-08-22 01:21:29 +05:30
if common . PolicyHasVariables ( * policy ) && variablesString == "" && valuesFile == "" {
return sanitizedError . NewWithError ( fmt . Sprintf ( "policy %s have variables. pass the values for the variables using set/values_file flag" , policy . Name ) , err )
}
2020-08-18 21:03:00 -07:00
for _ , resource := range resources {
2020-08-11 22:59:50 +05:30
// get values from file for this policy resource combination
2020-10-27 00:41:16 +05:30
thisPolicyResourceValues := make ( map [ string ] string )
2020-09-17 00:35:07 +05:30
if len ( valuesMap [ policy . GetName ( ) ] ) != 0 && ! reflect . DeepEqual ( valuesMap [ policy . GetName ( ) ] [ resource . GetName ( ) ] , Resource { } ) {
2020-10-27 00:41:16 +05:30
thisPolicyResourceValues = valuesMap [ policy . GetName ( ) ] [ resource . GetName ( ) ] . Values
2020-08-11 22:59:50 +05:30
}
for k , v := range variables {
2020-10-27 00:41:16 +05:30
thisPolicyResourceValues [ k ] = v
2020-08-11 22:59:50 +05:30
}
2020-10-27 00:41:16 +05:30
if common . PolicyHasVariables ( * policy ) && len ( thisPolicyResourceValues ) == 0 {
2020-08-12 13:39:06 +05:30
return sanitizedError . NewWithError ( fmt . Sprintf ( "policy %s have variables. pass the values for the variables using set/values_file flag" , policy . Name ) , err )
}
2020-10-30 16:38:19 +05:30
ers , err := applyPolicyOnResource ( policy , resource , mutateLogPath , mutateLogPathIsDir , thisPolicyResourceValues , rc , policyReport )
2020-03-06 03:00:18 +05:30
if err != nil {
2020-06-21 11:48:57 +05:30
return sanitizedError . NewWithError ( fmt . Errorf ( "failed to apply policy %v on resource %v" , policy . Name , resource . GetName ( ) ) . Error ( ) , err )
2020-03-06 03:00:18 +05:30
}
2020-10-27 00:41:16 +05:30
engineResponses = append ( engineResponses , ers ... )
2020-03-06 03:00:18 +05:30
}
}
2020-11-03 01:25:32 +05:30
printReportOrViolation ( policyReport , engineResponses , rc , resourcePaths )
2020-08-18 21:03:00 -07:00
2020-03-06 03:00:18 +05:30
return nil
} ,
}
cmd . Flags ( ) . StringArrayVarP ( & resourcePaths , "resource" , "r" , [ ] string { } , "Path to resource files" )
cmd . Flags ( ) . BoolVarP ( & cluster , "cluster" , "c" , false , "Checks if policies should be applied to cluster in the current context" )
2020-08-22 01:21:29 +05:30
cmd . Flags ( ) . StringVarP ( & mutateLogPath , "output" , "o" , "" , "Prints the mutated resources in provided file/directory" )
2020-08-05 23:53:27 +05:30
cmd . Flags ( ) . StringVarP ( & variablesString , "set" , "s" , "" , "Variables that are required" )
2020-11-05 23:14:58 +05:30
cmd . Flags ( ) . StringVarP ( & valuesFile , "values-file" , "f" , "" , "File containing values for policy variables" )
cmd . Flags ( ) . BoolVarP ( & policyReport , "policy-report" , "" , false , "Generates policy report when passed (default policyviolation r" )
2020-10-21 20:05:05 +05:30
cmd . Flags ( ) . StringVarP ( & namespace , "namespace" , "n" , "" , "Optional Policy parameter passed with cluster flag" )
2020-03-06 03:00:18 +05:30
return cmd
}
2020-10-30 16:38:19 +05:30
// getVariable - get the variables from console/file
func getVariable ( variablesString , valuesFile string ) ( variables map [ string ] string , valuesMap map [ string ] map [ string ] Resource , err error ) {
if variablesString != "" {
kvpairs := strings . Split ( strings . Trim ( variablesString , " " ) , "," )
for _ , kvpair := range kvpairs {
kvs := strings . Split ( strings . Trim ( kvpair , " " ) , "=" )
variables [ strings . Trim ( kvs [ 0 ] , " " ) ] = strings . Trim ( kvs [ 1 ] , " " )
}
}
if valuesFile != "" {
yamlFile , err := ioutil . ReadFile ( valuesFile )
if err != nil {
return variables , valuesMap , sanitizedError . NewWithError ( "unable to read yaml" , err )
}
valuesBytes , err := yaml . ToJSON ( yamlFile )
if err != nil {
return variables , valuesMap , sanitizedError . NewWithError ( "failed to convert json" , err )
}
values := & Values { }
if err := json . Unmarshal ( valuesBytes , values ) ; err != nil {
return variables , valuesMap , sanitizedError . NewWithError ( "failed to decode yaml" , err )
}
for _ , p := range values . Policies {
pmap := make ( map [ string ] Resource )
for _ , r := range p . Resources {
pmap [ r . Name ] = r
}
valuesMap [ p . Name ] = pmap
}
}
return variables , valuesMap , nil
}
// checkMutateLogPath - checking path for printing mutated resource (-o flag)
2020-11-03 01:25:32 +05:30
func checkMutateLogPath ( mutateLogPath string ) ( mutateLogPathIsDir bool , err error ) {
2020-10-30 16:38:19 +05:30
if mutateLogPath != "" {
spath := strings . Split ( mutateLogPath , "/" )
sfileName := strings . Split ( spath [ len ( spath ) - 1 ] , "." )
if sfileName [ len ( sfileName ) - 1 ] == "yml" || sfileName [ len ( sfileName ) - 1 ] == "yaml" {
mutateLogPathIsDir = false
} else {
mutateLogPathIsDir = true
}
err := createFileOrFolder ( mutateLogPath , mutateLogPathIsDir )
if err != nil {
if ! sanitizedError . IsErrorSanitized ( err ) {
return mutateLogPathIsDir , sanitizedError . NewWithError ( "failed to create file/folder." , err )
}
return mutateLogPathIsDir , err
}
}
return mutateLogPathIsDir , err
}
// getResourceAccordingToResourcePath - get resources according to the resource path
2020-11-03 01:25:32 +05:30
func getResourceAccordingToResourcePath ( resourcePaths [ ] string , cluster bool , policies [ ] * v1 . ClusterPolicy , dClient * client . Client , namespace string ) ( resources [ ] * unstructured . Unstructured , err error ) {
2020-10-30 16:38:19 +05:30
if len ( resourcePaths ) > 0 && resourcePaths [ 0 ] == "-" {
if common . IsInputFromPipe ( ) {
resourceStr := ""
scanner := bufio . NewScanner ( os . Stdin )
for scanner . Scan ( ) {
resourceStr = resourceStr + scanner . Text ( ) + "\n"
}
yamlBytes := [ ] byte ( resourceStr )
resources , err = common . GetResource ( yamlBytes )
if err != nil {
2020-11-03 01:25:32 +05:30
return resources , sanitizedError . NewWithError ( "failed to extract the resources" , err )
2020-10-30 16:38:19 +05:30
}
}
} else if ( len ( resourcePaths ) > 0 && resourcePaths [ 0 ] != "-" ) || len ( resourcePaths ) < 0 || cluster {
2020-11-03 01:25:32 +05:30
resources , err = common . GetResources ( policies , resourcePaths , dClient , cluster , namespace )
2020-10-30 16:38:19 +05:30
if err != nil {
2020-11-03 01:25:32 +05:30
return resources , sanitizedError . NewWithError ( "failed to load resources" , err )
2020-10-30 16:38:19 +05:30
}
}
2020-11-03 01:25:32 +05:30
return resources , err
2020-10-30 16:38:19 +05:30
}
// printReportOrViolation - printing policy report/violations
2020-11-03 01:25:32 +05:30
func printReportOrViolation ( policyReport bool , engineResponses [ ] response . EngineResponse , rc * resultCounts , resourcePaths [ ] string ) {
2020-10-30 16:38:19 +05:30
if policyReport {
resps := buildPolicyReports ( engineResponses )
if len ( resps ) > 0 {
2020-11-03 02:01:20 +05:30
fmt . Println ( "----------------------------------------------------------------------\nPOLICY REPORT:\n----------------------------------------------------------------------" )
2020-11-01 22:32:12 +05:30
report , _ := generateCLIraw ( resps )
yamlReport , _ := yaml1 . Marshal ( report )
fmt . Println ( string ( yamlReport ) )
2020-10-30 16:38:19 +05:30
} else {
2020-11-01 22:32:12 +05:30
fmt . Println ( "----------------------------------------------------------------------\nPOLICY REPORT: not generated as no validation failure" )
2020-10-30 16:38:19 +05:30
}
} else {
rcCount := rc . pass + rc . fail + rc . warn + rc . error + rc . skip
if rcCount < len ( resourcePaths ) {
rc . skip += len ( resourcePaths ) - rcCount
}
fmt . Printf ( "\npass: %d, fail: %d, warn: %d, error: %d, skip: %d \n" ,
rc . pass , rc . fail , rc . warn , rc . error , rc . skip )
if rc . fail > 0 || rc . error > 0 {
os . Exit ( 1 )
}
}
}
2020-07-21 00:41:30 +05:30
// applyPolicyOnResource - function to apply policy on resource
2020-11-03 01:25:32 +05:30
func applyPolicyOnResource ( policy * v1 . ClusterPolicy , resource * unstructured . Unstructured , mutateLogPath string , mutateLogPathIsDir bool , variables map [ string ] string , rc * resultCounts , policyReport bool ) ( [ ] response . EngineResponse , error ) {
2020-08-18 21:03:00 -07:00
responseError := false
2020-10-27 00:41:16 +05:30
engineResponses := make ( [ ] response . EngineResponse , 0 )
2020-08-18 21:03:00 -07:00
resPath := fmt . Sprintf ( "%s/%s/%s" , resource . GetNamespace ( ) , resource . GetKind ( ) , resource . GetName ( ) )
log . Log . V ( 3 ) . Info ( "applying policy on resource" , "policy" , policy . Name , "resource" , resPath )
2020-03-06 03:00:18 +05:30
2020-08-05 23:53:27 +05:30
ctx := context . NewContext ( )
for key , value := range variables {
startString := ""
endString := ""
for _ , k := range strings . Split ( key , "." ) {
startString += fmt . Sprintf ( ` { "%s": ` , k )
endString += ` } `
}
midString := fmt . Sprintf ( ` "%s" ` , value )
finalString := startString + midString + endString
var jsonData = [ ] byte ( finalString )
ctx . AddJSON ( jsonData )
}
mutateResponse := engine . Mutate ( engine . PolicyContext { Policy : * policy , NewResource : * resource , Context : ctx } )
2020-10-27 00:41:16 +05:30
engineResponses = append ( engineResponses , mutateResponse )
2020-06-30 11:53:27 -07:00
if ! mutateResponse . IsSuccessful ( ) {
2020-08-18 21:03:00 -07:00
fmt . Printf ( "Failed to apply mutate policy %s -> resource %s" , policy . Name , resPath )
2020-03-06 03:00:18 +05:30
for i , r := range mutateResponse . PolicyResponse . Rules {
fmt . Printf ( "\n%d. %s" , i + 1 , r . Message )
}
2020-08-18 21:03:00 -07:00
responseError = true
2020-03-06 03:00:18 +05:30
} else {
if len ( mutateResponse . PolicyResponse . Rules ) > 0 {
yamlEncodedResource , err := yamlv2 . Marshal ( mutateResponse . PatchedResource . Object )
if err != nil {
2020-08-18 21:03:00 -07:00
rc . error ++
2020-03-06 03:00:18 +05:30
}
2020-09-17 00:35:07 +05:30
if mutateLogPath == "" {
mutatedResource := string ( yamlEncodedResource )
if len ( strings . TrimSpace ( mutatedResource ) ) > 0 {
fmt . Printf ( "\nmutate policy %s applied to %s:" , policy . Name , resPath )
fmt . Printf ( "\n" + mutatedResource )
fmt . Printf ( "\n" )
}
} else {
err := printMutatedOutput ( mutateLogPath , mutateLogPathIsDir , string ( yamlEncodedResource ) , resource . GetName ( ) + "-mutated" )
if err != nil {
2020-10-27 00:41:16 +05:30
return engineResponses , sanitizedError . NewWithError ( "failed to print mutated result" , err )
2020-09-17 00:35:07 +05:30
}
fmt . Printf ( "\n\nMutation:\nMutation has been applied succesfully. Check the files." )
2020-07-21 00:41:30 +05:30
}
2020-08-12 13:39:06 +05:30
2020-03-06 03:00:18 +05:30
}
}
2020-11-10 02:37:55 +05:30
if resource . GetKind ( ) == "Pod" && len ( resource . GetOwnerReferences ( ) ) > 0 {
if policy . HasAutoGenAnnotation ( ) {
if _ , ok := policy . GetAnnotations ( ) [ engine . PodControllersAnnotation ] ; ok {
delete ( policy . Annotations , engine . PodControllersAnnotation )
}
}
}
2020-08-05 23:53:27 +05:30
validateResponse := engine . Validate ( engine . PolicyContext { Policy : * policy , NewResource : mutateResponse . PatchedResource , Context : ctx } )
2020-10-27 00:41:16 +05:30
engineResponses = append ( engineResponses , validateResponse )
2020-10-30 16:38:19 +05:30
if ! policyReport {
if ! validateResponse . IsSuccessful ( ) {
fmt . Printf ( "\npolicy %s -> resource %s failed: \n" , policy . Name , resPath )
for i , r := range validateResponse . PolicyResponse . Rules {
if ! r . Success {
fmt . Printf ( "%d. %s: %s \n" , i + 1 , r . Name , r . Message )
}
2020-08-18 21:03:00 -07:00
}
2020-10-30 16:38:19 +05:30
responseError = true
}
2020-03-06 03:00:18 +05:30
}
var policyHasGenerate bool
for _ , rule := range policy . Spec . Rules {
if rule . HasGenerate ( ) {
policyHasGenerate = true
}
}
if policyHasGenerate {
generateResponse := engine . Generate ( engine . PolicyContext { Policy : * policy , NewResource : * resource } )
2020-10-27 00:41:16 +05:30
engineResponses = append ( engineResponses , generateResponse )
2020-03-06 03:00:18 +05:30
if len ( generateResponse . PolicyResponse . Rules ) > 0 {
2020-08-18 21:03:00 -07:00
log . Log . V ( 3 ) . Info ( "generate resource is valid" , "policy" , policy . Name , "resource" , resPath )
2020-03-06 03:00:18 +05:30
} else {
2020-08-18 21:03:00 -07:00
fmt . Printf ( "generate policy %s resource %s is invalid \n" , policy . Name , resPath )
2020-03-06 03:00:18 +05:30
for i , r := range generateResponse . PolicyResponse . Rules {
2020-08-18 21:03:00 -07:00
fmt . Printf ( "%d. %s \b" , i + 1 , r . Message )
2020-03-06 03:00:18 +05:30
}
2020-08-18 21:03:00 -07:00
responseError = true
2020-03-06 03:00:18 +05:30
}
}
2020-08-18 21:03:00 -07:00
if responseError == true {
rc . fail ++
} else {
rc . pass ++
}
2020-10-21 20:05:05 +05:30
2020-10-27 00:41:16 +05:30
return engineResponses , nil
2020-03-06 03:00:18 +05:30
}
2020-07-21 00:41:30 +05:30
2020-07-29 21:41:58 +05:30
// mutatePolicies - function to apply mutation on policies
func mutatePolices ( policies [ ] * v1 . ClusterPolicy ) ( [ ] * v1 . ClusterPolicy , error ) {
2020-07-21 00:41:30 +05:30
newPolicies := make ( [ ] * v1 . ClusterPolicy , 0 )
logger := log . Log . WithName ( "apply" )
for _ , policy := range policies {
2020-07-29 21:41:58 +05:30
p , err := common . MutatePolicy ( policy , logger )
2020-07-21 00:41:30 +05:30
if err != nil {
2020-07-29 21:41:58 +05:30
if ! sanitizedError . IsErrorSanitized ( err ) {
return nil , sanitizedError . NewWithError ( "failed to mutate policy." , err )
}
return nil , err
2020-07-21 00:41:30 +05:30
}
2020-07-29 21:41:58 +05:30
newPolicies = append ( newPolicies , p )
2020-07-21 00:41:30 +05:30
}
return newPolicies , nil
}
// printMutatedOutput - function to print output in provided file or directory
2020-08-22 01:21:29 +05:30
func printMutatedOutput ( mutateLogPath string , mutateLogPathIsDir bool , yaml string , fileName string ) error {
2020-07-21 00:41:30 +05:30
var f * os . File
var err error
yaml = yaml + ( "\n---\n\n" )
2020-08-22 01:21:29 +05:30
if ! mutateLogPathIsDir {
f , err = os . OpenFile ( mutateLogPath , os . O_APPEND | os . O_WRONLY , 0644 )
2020-07-21 00:41:30 +05:30
} else {
2020-08-22 01:21:29 +05:30
f , err = os . OpenFile ( mutateLogPath + "/" + fileName + ".yaml" , os . O_APPEND | os . O_CREATE | os . O_WRONLY , 0644 )
2020-07-21 00:41:30 +05:30
}
if err != nil {
return err
}
if _ , err := f . Write ( [ ] byte ( yaml ) ) ; err != nil {
f . Close ( )
return err
}
if err := f . Close ( ) ; err != nil {
return err
}
return nil
}
2020-08-18 21:03:00 -07:00
// createFileOrFolder - creating file or folder according to path provided
2020-08-22 01:21:29 +05:30
func createFileOrFolder ( mutateLogPath string , mutateLogPathIsDir bool ) error {
mutateLogPath = filepath . Clean ( mutateLogPath )
_ , err := os . Stat ( mutateLogPath )
2020-07-21 00:41:30 +05:30
if err != nil {
if os . IsNotExist ( err ) {
2020-08-22 01:21:29 +05:30
if ! mutateLogPathIsDir {
2020-07-21 00:41:30 +05:30
// check the folder existance, then create the file
2020-07-21 10:33:38 +05:30
var folderPath string
2020-08-22 01:21:29 +05:30
s := strings . Split ( mutateLogPath , "/" )
2020-07-21 10:33:38 +05:30
if len ( s ) > 1 {
2020-08-22 01:21:29 +05:30
folderPath = mutateLogPath [ : len ( mutateLogPath ) - len ( s [ len ( s ) - 1 ] ) - 1 ]
2020-07-21 10:33:38 +05:30
_ , err := os . Stat ( folderPath )
if os . IsNotExist ( err ) {
errDir := os . MkdirAll ( folderPath , 0755 )
if errDir != nil {
return sanitizedError . NewWithError ( fmt . Sprintf ( "failed to create directory" ) , err )
}
2020-07-21 00:41:30 +05:30
}
}
2020-08-22 01:21:29 +05:30
file , err := os . OpenFile ( mutateLogPath , os . O_RDONLY | os . O_CREATE , 0644 )
2020-07-21 00:41:30 +05:30
if err != nil {
return sanitizedError . NewWithError ( fmt . Sprintf ( "failed to create file" ) , err )
}
err = file . Close ( )
if err != nil {
return sanitizedError . NewWithError ( fmt . Sprintf ( "failed to close file" ) , err )
}
} else {
2020-08-22 01:21:29 +05:30
errDir := os . MkdirAll ( mutateLogPath , 0755 )
2020-07-21 00:41:30 +05:30
if errDir != nil {
return sanitizedError . NewWithError ( fmt . Sprintf ( "failed to create directory" ) , err )
}
}
} else {
return sanitizedError . NewWithError ( fmt . Sprintf ( "failed to describe file" ) , err )
}
}
return nil
}