github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/generator/helper/resources.go (about) 1 package helper 2 3 import ( 4 "bytes" 5 "fmt" 6 "text/template" 7 8 "github.com/SAP/jenkins-library/pkg/piperutils" 9 ) 10 11 // PiperEnvironmentResource defines a piper environement resource which stores data across multiple pipeline steps 12 type PiperEnvironmentResource struct { 13 Name string 14 StepName string 15 Parameters []PiperEnvironmentParameter 16 Categories []string 17 } 18 19 // PiperEnvironmentParameter defines a parameter within the Piper environment 20 type PiperEnvironmentParameter struct { 21 Category string 22 Name string 23 Type string 24 } 25 26 const piperEnvStructTemplate = `type {{ .StepName }}{{ .Name | title}} struct { 27 {{- range $notused, $param := .Parameters }} 28 {{- if not $param.Category}} 29 {{ $param.Name | golangName }} {{ $param.Type | resourceFieldType }} 30 {{- end }} 31 {{- end }} 32 {{- range $notused, $category := .Categories }} 33 {{ $category }} struct { 34 {{- range $notused, $param := $.Parameters }} 35 {{- if eq $category $param.Category }} 36 {{ $param.Name | golangName }} {{ $param.Type | resourceFieldType }} 37 {{- end }} 38 {{- end }} 39 } 40 {{- end }} 41 } 42 43 func (p *{{ .StepName }}{{ .Name | title}}) persist(path, resourceName string) { 44 content := []struct{ 45 category string 46 name string 47 value interface{} 48 }{ 49 {{- range $notused, $param := .Parameters }} 50 {{- if not $param.Category}} 51 {category: "", name: "{{ $param.Name }}", value: p.{{ $param.Name | golangName}}}, 52 {{- else }} 53 {category: "{{ $param.Category }}", name: "{{ $param.Name }}", value: p.{{ $param.Category }}.{{ $param.Name | golangName}}}, 54 {{- end }} 55 {{- end }} 56 } 57 58 errCount := 0 59 for _, param := range content { 60 err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value) 61 if err != nil { 62 log.Entry().WithError(err).Error("Error persisting piper environment.") 63 errCount++ 64 } 65 } 66 if errCount > 0 { 67 log.Entry().Error("failed to persist Piper environment") 68 } 69 }` 70 71 // StructName returns the name of the environment resource struct 72 func (p *PiperEnvironmentResource) StructName() string { 73 return fmt.Sprintf("%v%v", p.StepName, piperutils.Title(p.Name)) 74 } 75 76 // StructString returns the golang coding for the struct definition of the environment resource 77 func (p *PiperEnvironmentResource) StructString() (string, error) { 78 funcMap := template.FuncMap{ 79 "title": piperutils.Title, 80 "golangName": golangName, 81 "resourceFieldType": resourceFieldType, 82 } 83 84 tmpl, err := template.New("resources").Funcs(funcMap).Parse(piperEnvStructTemplate) 85 if err != nil { 86 return "", err 87 } 88 89 var generatedCode bytes.Buffer 90 err = tmpl.Execute(&generatedCode, &p) 91 if err != nil { 92 return "", err 93 } 94 95 return string(generatedCode.Bytes()), nil 96 } 97 98 // InfluxResource defines an Influx resouece that holds measurement information for a pipeline run 99 type InfluxResource struct { 100 Name string 101 StepName string 102 Measurements []InfluxMeasurement 103 } 104 105 // InfluxMeasurement defines a measurement for Influx reporting which is defined via a step resource 106 type InfluxMeasurement struct { 107 Name string 108 Fields []InfluxMetric 109 Tags []InfluxMetric 110 } 111 112 // InfluxMetric defines a metric (column) in an influx measurement 113 type InfluxMetric struct { 114 Name string 115 Type string 116 } 117 118 // InfluxMetricContent defines the content of an Inflx metric 119 type InfluxMetricContent struct { 120 Measurement string 121 ValType string 122 Name string 123 Value *string 124 } 125 126 const influxStructTemplate = `type {{ .StepName }}{{ .Name | title}} struct { 127 {{- range $notused, $measurement := .Measurements }} 128 {{ $measurement.Name }} struct { 129 fields struct { 130 {{- range $notused, $field := $measurement.Fields }} 131 {{ $field.Name | golangName }} {{ $field.Type | resourceFieldType }} 132 {{- end }} 133 } 134 tags struct { 135 {{- range $notused, $tag := $measurement.Tags }} 136 {{ $tag.Name | golangName }} {{ $tag.Type | resourceFieldType }} 137 {{- end }} 138 } 139 } 140 {{- end }} 141 } 142 143 func (i *{{ .StepName }}{{ .Name | title}}) persist(path, resourceName string) { 144 measurementContent := []struct{ 145 measurement string 146 valType string 147 name string 148 value interface{} 149 }{ 150 {{- range $notused, $measurement := .Measurements }} 151 {{- range $notused, $field := $measurement.Fields }} 152 {valType: config.InfluxField, measurement: "{{ $measurement.Name }}" , name: "{{ $field.Name }}", value: i.{{ $measurement.Name }}.fields.{{ $field.Name | golangName }}}, 153 {{- end }} 154 {{- range $notused, $tag := $measurement.Tags }} 155 {valType: config.InfluxTag, measurement: "{{ $measurement.Name }}" , name: "{{ $tag.Name }}", value: i.{{ $measurement.Name }}.tags.{{ $tag.Name | golangName }}}, 156 {{- end }} 157 {{- end }} 158 } 159 160 errCount := 0 161 for _, metric := range measurementContent { 162 err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(metric.measurement, fmt.Sprintf("%vs", metric.valType), metric.name), metric.value) 163 if err != nil { 164 log.Entry().WithError(err).Error("Error persisting influx environment.") 165 errCount++ 166 } 167 } 168 if errCount > 0 { 169 log.Entry().Error("failed to persist Influx environment") 170 } 171 }` 172 173 // StructString returns the golang coding for the struct definition of the InfluxResource 174 func (i *InfluxResource) StructString() (string, error) { 175 funcMap := template.FuncMap{ 176 "title": piperutils.Title, 177 "golangName": golangName, 178 "resourceFieldType": resourceFieldType, 179 } 180 181 tmpl, err := template.New("resources").Funcs(funcMap).Parse(influxStructTemplate) 182 if err != nil { 183 return "", err 184 } 185 186 var generatedCode bytes.Buffer 187 err = tmpl.Execute(&generatedCode, &i) 188 if err != nil { 189 return "", err 190 } 191 192 return string(generatedCode.Bytes()), nil 193 } 194 195 // StructName returns the name of the influx resource struct 196 func (i *InfluxResource) StructName() string { 197 return fmt.Sprintf("%v%v", i.StepName, piperutils.Title(i.Name)) 198 } 199 200 // PiperEnvironmentResource defines a piper environement resource which stores data across multiple pipeline steps 201 type ReportsResource struct { 202 Name string 203 StepName string 204 Parameters []ReportsParameter 205 } 206 207 // PiperEnvironmentParameter defines a parameter within the Piper environment 208 type ReportsParameter struct { 209 FilePattern string 210 ParamRef string 211 Type string 212 } 213 214 const reportsStructTemplate = `type {{ .StepName }}{{ .Name | title}} struct { 215 } 216 217 func (p *{{ .StepName }}{{ .Name | title}}) persist(stepConfig {{ .StepName }}Options, gcpJsonKeyFilePath string, gcsBucketId string, gcsFolderPath string, gcsSubFolder string) { 218 if gcsBucketId == "" { 219 log.Entry().Info("persisting reports to GCS is disabled, because gcsBucketId is empty") 220 return 221 } 222 log.Entry().Info("Uploading reports to Google Cloud Storage...") 223 content := []gcs.ReportOutputParam{ 224 {{- range $notused, $param := .Parameters }} 225 {FilePattern: "{{ $param.FilePattern }}", ParamRef: "{{ $param.ParamRef }}", StepResultType: "{{ $param.Type }}"}, 226 {{- end }} 227 } 228 envVars := []gcs.EnvVar{ 229 {Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: gcpJsonKeyFilePath, Modified: false}, 230 } 231 gcsClient, err := gcs.NewClient(gcs.WithEnvVars(envVars)) 232 if err != nil { 233 log.Entry().Errorf("creation of GCS client failed: %v", err) 234 return 235 } 236 defer gcsClient.Close() 237 structVal := reflect.ValueOf(&stepConfig).Elem() 238 inputParameters := map[string]string{} 239 for i := 0; i < structVal.NumField(); i++ { 240 field := structVal.Type().Field(i) 241 if field.Type.String() == "string" { 242 paramName := strings.Split(field.Tag.Get("json"), ",") 243 paramValue, _ := structVal.Field(i).Interface().(string) 244 inputParameters[paramName[0]] = paramValue 245 } 246 } 247 if err := gcs.PersistReportsToGCS(gcsClient, content, inputParameters, gcsFolderPath, gcsBucketId, gcsSubFolder, doublestar.Glob, os.Stat); err != nil { 248 log.Entry().Errorf("failed to persist reports: %v", err) 249 } 250 }` 251 252 // StructName returns the name of the environment resource struct 253 func (p *ReportsResource) StructName() string { 254 return fmt.Sprintf("%v%v", p.StepName, piperutils.Title(p.Name)) 255 } 256 257 // StructString returns the golang coding for the struct definition of the environment resource 258 func (p *ReportsResource) StructString() (string, error) { 259 funcMap := template.FuncMap{ 260 "title": piperutils.Title, 261 "golangName": golangName, 262 "resourceFieldType": resourceFieldType, 263 } 264 265 tmpl, err := template.New("resources").Funcs(funcMap).Parse(reportsStructTemplate) 266 if err != nil { 267 return "", err 268 } 269 270 var generatedCode bytes.Buffer 271 err = tmpl.Execute(&generatedCode, &p) 272 if err != nil { 273 return "", err 274 } 275 276 return string(generatedCode.String()), nil 277 }