diff --git a/.goreleaser-linux.yml b/.goreleaser-linux.yml new file mode 100644 index 0000000..d1e6f36 --- /dev/null +++ b/.goreleaser-linux.yml @@ -0,0 +1,32 @@ +# This is an example .goreleaser.yml file with some sensible defaults. +# Make sure to check the documentation at https://goreleaser.com +before: + hooks: + # You may remove this if you don't use go modules. + - go mod tidy + # you may remove this if you don't need go generate + - go generate ./... +builds: + - env: + - CGO_ENABLED=1 + goos: + - linux + goarch: + - amd64 + - 386 +archives: + - replacements: + darwin: Darwin + linux: Linux + 386: i386 + amd64: x86_64 +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ incpatch .Version }}" +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e69de29..61d98e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -0,0 +1,14 @@ +## adding support for a new source type + + +###### implement a new package under `libs` for that source + +The package should expose function `IsSource` that given a parsed SLO object returns true if the source is supported by the package. +An example for sumologic source detection is [here](https://github.com/OpenSLO/slogen/blob/sumo-agaurav/libs/sumologic/tf.go#L78-L92) + +The package should also expose a function `GiveTerraform` that returns the terraform content to be added for that source when provided with the parsed slo configs. +The above function can then be called in [`libs/gen.go`](https://github.com/OpenSLO/slogen/blob/sumo-agaurav/libs/gen.go#L111) to create the corresponding terraform files. + + +###### add the required terraform providers for that source in [libs/templates/terraform//main.tf.gotf](libs/templates/terraform/main.tf.gotf) + diff --git a/libs/gen.go b/libs/gen.go index ec4cb9b..b9a6d56 100644 --- a/libs/gen.go +++ b/libs/gen.go @@ -18,7 +18,6 @@ var tfTemplates *template.Template const NameDashboardTmpl = "dashboard.tf.gotf" const NameViewTmpl = "sched-view.tf.gotf" const NameMonitorTmpl = "monitor.tf.gotf" -const NameMainTmpl = "main.tf.gotf" const NameModuleTmpl = "module_interface.tf.gotf" const NameDashFolderTmpl = "dash-folders.tf.gotf" const NameMonitorFolderTmpl = "monitor-folders.tf.gotf" @@ -29,6 +28,9 @@ const NameServiceTrackerTmpl = "service-overview.tf.gotf" //go:embed templates/terraform/**/*.tf.gotf var tmplFiles embed.FS +//go:embed templates/terraform/main.tf.gotf +var tmplMainTFStr string + var alertPolicyMap = map[string]oslo.AlertPolicy{} var notificationTargetMap = map[string]oslo.AlertNotificationTarget{} @@ -90,6 +92,47 @@ func GenTerraform(slosMv map[string]*SLOMultiVerse, c GenConf) (string, error) { return genTerraformForAlpha(slosAlpha, c) } +func genTerraformForV1(slos map[string]*SLOMultiVerse, c GenConf) error { + + v1Path := filepath.Join(c.OutDir, NativeSLOFolder) + + fillAlertPolicyMap(slos) + fillNotificationTargetMap(slos) + + srvMap := map[string]bool{} + + var err error + var sloStr, monitorsStr string + + for _, sloM := range slos { + if sloM.SLO != nil { + slo := sloM.SLO + + // handle sumologic specific stuff + if sumologic.IsSource(*slo) { + sloStr, monitorsStr, err = sumologic.GiveTerraform(alertPolicyMap, notificationTargetMap, *slo) + } + + err = os.WriteFile(filepath.Join(v1Path, fmt.Sprintf("slo_%s.tf", slo.Metadata.Name)), []byte(sloStr), 0755) + if err != nil { + return err + } + srvMap[slo.Spec.Service] = true + + if monitorsStr != "" { + err = os.WriteFile(filepath.Join(v1Path, fmt.Sprintf("slo_monitors_%s.tf", slo.Metadata.Name)), []byte(monitorsStr), 0755) + } + } + } + + srvList := GiveKeys(srvMap) + sort.Strings(srvList) + + GenSLOFoldersTF(srvList, c) + + return nil +} + func genTerraformForAlpha(slosAlpha map[string]*SLOv1Alpha, c GenConf) (string, error) { var err error @@ -146,56 +189,6 @@ func fillNotificationTargetMap(slos map[string]*SLOMultiVerse) { } } -func genTerraformForV1(slos map[string]*SLOMultiVerse, c GenConf) error { - - v1Path := filepath.Join(c.OutDir, NativeSLOFolder) - - fillAlertPolicyMap(slos) - fillNotificationTargetMap(slos) - - srvMap := map[string]bool{} - - for _, sloM := range slos { - if sloM.SLO != nil { - slo := sloM.SLO - sumoSLO, err := sumologic.ConvertToSumoSLO(*slo) - sumoSLOStr, err := sumologic.GiveSLOTerraform(*slo) - - if err != nil { - BadUResult(err.Error() + fmt.Sprintf("| file : %s", sloM.ConfigPath)) - return err - } - - //pretty.Println(sumoSLO) - - err = os.WriteFile(filepath.Join(v1Path, fmt.Sprintf("slo_%s.tf", slo.Metadata.Name)), []byte(sumoSLOStr), 0755) - if err != nil { - return err - } - - srvMap[slo.Spec.Service] = true - - monitorsStr, err := sumologic.GenSLOMonitorsFromAPNames(alertPolicyMap, notificationTargetMap, - *sumoSLO, *slo.SLO) - - if err != nil { - return err - } - - if monitorsStr != "" { - err = os.WriteFile(filepath.Join(v1Path, fmt.Sprintf("slo_monitors_%s.tf", slo.Metadata.Name)), []byte(monitorsStr), 0755) - } - } - } - - srvList := GiveKeys(srvMap) - sort.Strings(srvList) - - GenSLOFoldersTF(srvList, c) - - return nil -} - func splitMultiVerse(slos map[string]*SLOMultiVerse) (map[string]*SLOv1Alpha, map[string]*specs.OpenSLOSpec) { alpha := map[string]*SLOv1Alpha{} @@ -266,7 +259,7 @@ func SetupOutDir(c GenConf) error { mainPath := filepath.Join(c.OutDir, "main.tf") - err = FileFromTmpl(NameMainTmpl, mainPath, c) + err = GenMainTF(mainPath, c) if err != nil { return err } @@ -302,6 +295,20 @@ func SetupOutDir(c GenConf) error { return nil } +func GenMainTF(path string, conf GenConf) error { + mainTFTmpl := template.Must(template.New("main.tf").Parse(tmplMainTFStr)) + + buff := &bytes.Buffer{} + + err := mainTFTmpl.Execute(buff, conf) + + if err != nil { + return err + } + + return os.WriteFile(path, buff.Bytes(), 0644) +} + func FileFromTmpl(name string, path string, data interface{}) error { moduleTmpl := tfTemplates.Lookup(name) buff := &bytes.Buffer{} diff --git a/libs/sumologic/native.go b/libs/sumologic/native.go index 9b150a6..7944f18 100644 --- a/libs/sumologic/native.go +++ b/libs/sumologic/native.go @@ -29,6 +29,11 @@ const ( AlertConditionTypeSLI = "sli" ) +const ( + SourceTypeLogs = "sumologic-logs" + SourceTypeMetrics = "sumologic-metrics" +) + type SLOMonitor struct { Service string SLOName string @@ -145,9 +150,9 @@ func giveSLI(slo specs.OpenSLOSpec) (*sumotf.SLOIndicator, error) { if indicator.Spec.RatioMetric != nil { switch indicator.Spec.RatioMetric.Total.MetricSource.Type { - case "sumologic-logs": + case SourceTypeLogs: queryType = "Logs" - case "sumologic-metrics": + case SourceTypeMetrics: queryType = "Metrics" } @@ -185,9 +190,9 @@ func giveSLI(slo specs.OpenSLOSpec) (*sumotf.SLOIndicator, error) { if indicator.Spec.ThresholdMetric != nil { switch indicator.Spec.ThresholdMetric.MetricSource.Type { - case "sumologic-logs": + case SourceTypeLogs: queryType = "Logs" - case "sumologic-metrics": + case SourceTypeMetrics: queryType = "Metrics" } @@ -417,8 +422,20 @@ func mergeSLIMonitors(mons map[string][]SLOMonitor) []SLOMonitor { return mergedMonitors } +func GiveSLOMonitorTerraform(apMap map[string]oslo.AlertPolicy, ntMap map[string]oslo.AlertNotificationTarget, + slo specs.OpenSLOSpec) (string, error) { + sumoSLO, err := ConvertToSumoSLO(slo) + + if err != nil { + return "", err + } + + return GenSLOMonitorsFromAPNames(apMap, ntMap, sumoSLO, *slo.SLO) + +} + func GenSLOMonitorsFromAPNames(apMap map[string]oslo.AlertPolicy, ntMap map[string]oslo.AlertNotificationTarget, - sumoSLO SLO, slo oslo.SLO) (string, error) { + sumoSLO *SLO, slo oslo.SLO) (string, error) { var sloMonitors []SLOMonitor @@ -428,7 +445,7 @@ func GenSLOMonitorsFromAPNames(apMap map[string]oslo.AlertPolicy, ntMap map[stri ap := apMap[apName] - mons, err := ConvertToSumoMonitor(ap, &sumoSLO, ntMap) + mons, err := ConvertToSumoMonitor(ap, sumoSLO, ntMap) if err != nil { return "", err } diff --git a/libs/sumologic/tf.go b/libs/sumologic/tf.go index ce29b34..aebe4df 100644 --- a/libs/sumologic/tf.go +++ b/libs/sumologic/tf.go @@ -4,6 +4,7 @@ import ( "bytes" "embed" "github.com/OpenSLO/slogen/libs/specs" + oslo "github.com/agaurav/oslo/pkg/manifest/v1" "text/template" ) @@ -27,6 +28,19 @@ func init() { } } +func GiveTerraform(apMap map[string]oslo.AlertPolicy, ntMap map[string]oslo.AlertNotificationTarget, + slo specs.OpenSLOSpec) (string, string, error) { + sloStr, err := GiveSLOTerraform(slo) + + if err != nil { + return "", "", err + } + + monitorsStr, err := GiveSLOMonitorTerraform(apMap, ntMap, slo) + + return sloStr, monitorsStr, err +} + func GiveSLOTerraform(s specs.OpenSLOSpec) (string, error) { sumoSLO, err := ConvertToSumoSLO(s) @@ -60,3 +74,19 @@ func GiveMonitorTerraform(mons []SLOMonitor) (string, error) { return buff.String(), nil } + +func IsSource(slo specs.OpenSLOSpec) bool { + indicator := slo.Spec.Indicator + + sourceType := "" + + if indicator.Spec.RatioMetric != nil { + sourceType = indicator.Spec.RatioMetric.Total.MetricSource.Type + } + + if indicator.Spec.ThresholdMetric != nil { + sourceType = indicator.Spec.ThresholdMetric.MetricSource.Type + } + + return sourceType == SourceTypeLogs || sourceType == SourceTypeMetrics +} diff --git a/libs/templates/terraform/sumologic/main.tf.gotf b/libs/templates/terraform/main.tf.gotf similarity index 97% rename from libs/templates/terraform/sumologic/main.tf.gotf rename to libs/templates/terraform/main.tf.gotf index 1c93ce5..f684e81 100644 --- a/libs/templates/terraform/sumologic/main.tf.gotf +++ b/libs/templates/terraform/main.tf.gotf @@ -7,8 +7,27 @@ terraform { } +resource "sumologic_slo_folder" "slo_root_folder" { + name = "{{.SLORootFolder}}" + description = "Root folder for native SLOs created with slogen" +} + +resource "sumologic_monitor_folder" "slo_monitor_root_folder" { + name = "{{.SLOMonitorRootFolder}}" + description = "Root folder for SLO based monitors created with slogen" +} + +module "slos" { + source = "./slos" + slo_root_folder_id = sumologic_slo_folder.slo_root_folder.id + slo_monitor_root_folder_id = sumologic_monitor_folder.slo_monitor_root_folder.id +} + + {{- if not .OnlyNative }} +/// legacy sumo slo's for sloV1Alpha + {{- if .AsModule }} variable "slogen_dashboards_parent_folder" {} {{else}} @@ -48,19 +67,3 @@ module "slg_tf_monitors" { depends_on = [module.slg_tf_views] } {{- end }} - -resource "sumologic_slo_folder" "slo_root_folder" { - name = "{{.SLORootFolder}}" - description = "Root folder for native SLOs created with slogen" -} - -resource "sumologic_monitor_folder" "slo_monitor_root_folder" { - name = "{{.SLOMonitorRootFolder}}" - description = "Root folder for SLO based monitors created with slogen" -} - -module "slos" { - source = "./slos" - slo_root_folder_id = sumologic_slo_folder.slo_root_folder.id - slo_monitor_root_folder_id = sumologic_monitor_folder.slo_monitor_root_folder.id -}