1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-04 04:07:16 +02:00

Added go-based influxWriteData step (#2890)

* Added go-based influxWriteData step

* Wrote tests & fixed issues

* Fixed issues

* Created go-based step tests. Fixed issues

* Fixed issues

* Integration test was added

Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
Co-authored-by: Sven Merk <33895725+nevskrem@users.noreply.github.com>
This commit is contained in:
Siarhei Pazdniakou 2021-06-30 12:18:49 +03:00 committed by GitHub
parent 3f6eb603c7
commit 54f2a0d471
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 988 additions and 5 deletions

42
cmd/influxWriteData.go Normal file
View File

@ -0,0 +1,42 @@
package cmd
import (
"encoding/json"
"fmt"
"github.com/SAP/jenkins-library/pkg/influx"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/telemetry"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
)
func influxWriteData(config influxWriteDataOptions, _ *telemetry.CustomData) {
influxClient := influxdb2.NewClient(config.ServerURL, config.AuthToken)
// Error situations should be bubbled up until they reach the line below which will then stop execution
// through the log.Entry().Fatal() call leading to an os.Exit(1) in the end.
err := writeData(&config, influxClient)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func writeData(config *influxWriteDataOptions, influxClient influxdb2.Client) error {
log.Entry().Info("influxWriteData step")
client := influx.NewClient(influxClient, config.Organization, config.Bucket)
var dataMap map[string]map[string]interface{}
if err := json.Unmarshal([]byte(config.DataMap), &dataMap); err != nil {
return fmt.Errorf("Failed to unmarshal dataMap: %v", err)
}
var dataMapTags map[string]map[string]string
if config.DataMapTags != "" {
if err := json.Unmarshal([]byte(config.DataMapTags), &dataMapTags); err != nil {
return fmt.Errorf("Failed to unmarshal dataMapTags: %v", err)
}
}
if err := client.WriteMetrics(dataMap, dataMapTags); err != nil {
return err
}
log.Entry().Info("Metrics have been written successfully")
return nil
}

View File

@ -0,0 +1,196 @@
// Code generated by piper's step-generator. DO NOT EDIT.
package cmd
import (
"fmt"
"os"
"time"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/splunk"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/spf13/cobra"
)
type influxWriteDataOptions struct {
ServerURL string `json:"serverUrl,omitempty"`
AuthToken string `json:"authToken,omitempty"`
Bucket string `json:"bucket,omitempty"`
Organization string `json:"organization,omitempty"`
DataMap string `json:"dataMap,omitempty"`
DataMapTags string `json:"dataMapTags,omitempty"`
}
// InfluxWriteDataCommand Writes metrics to influxdb
func InfluxWriteDataCommand() *cobra.Command {
const STEP_NAME = "influxWriteData"
metadata := influxWriteDataMetadata()
var stepConfig influxWriteDataOptions
var startTime time.Time
var logCollector *log.CollectorHook
var createInfluxWriteDataCmd = &cobra.Command{
Use: STEP_NAME,
Short: "Writes metrics to influxdb",
Long: `In this step, the metrics are written to the timeseries database [InfluxDB](https://www.influxdata.com/time-series-platform/influxdb/)`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
log.SetVerbose(GeneralConfig.Verbose)
path, _ := os.Getwd()
fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
log.RegisterHook(fatalHook)
err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile)
if err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return err
}
log.RegisterSecret(stepConfig.AuthToken)
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
log.RegisterHook(&sentryHook)
}
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID}
log.RegisterHook(logCollector)
}
return nil
},
Run: func(_ *cobra.Command, _ []string) {
telemetryData := telemetry.CustomData{}
telemetryData.ErrorCode = "1"
handler := func() {
config.RemoveVaultSecretFiles()
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
telemetryData.ErrorCategory = log.GetErrorCategory().String()
telemetry.Send(&telemetryData)
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunk.Send(&telemetryData, logCollector)
}
}
log.DeferExitHandler(handler)
defer handler()
telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunk.Initialize(GeneralConfig.CorrelationID,
GeneralConfig.HookConfig.SplunkConfig.Dsn,
GeneralConfig.HookConfig.SplunkConfig.Token,
GeneralConfig.HookConfig.SplunkConfig.Index,
GeneralConfig.HookConfig.SplunkConfig.SendLogs)
}
influxWriteData(stepConfig, &telemetryData)
telemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addInfluxWriteDataFlags(createInfluxWriteDataCmd, &stepConfig)
return createInfluxWriteDataCmd
}
func addInfluxWriteDataFlags(cmd *cobra.Command, stepConfig *influxWriteDataOptions) {
cmd.Flags().StringVar(&stepConfig.ServerURL, "serverUrl", os.Getenv("PIPER_serverUrl"), "Base URL to the InfluxDB server")
cmd.Flags().StringVar(&stepConfig.AuthToken, "authToken", os.Getenv("PIPER_authToken"), "Token to authenticate to the Influxdb")
cmd.Flags().StringVar(&stepConfig.Bucket, "bucket", `piper`, "Name of database (1.8) or bucket (2.0)")
cmd.Flags().StringVar(&stepConfig.Organization, "organization", os.Getenv("PIPER_organization"), "Name of influx organization. Only for Influxdb 2.0")
cmd.Flags().StringVar(&stepConfig.DataMap, "dataMap", os.Getenv("PIPER_dataMap"), "Map of fields for each measurements. It has to be a JSON string. For example: {'series_1':{'field_a':11,'field_b':12},'series_2':{'field_c':21,'field_d':22}}")
cmd.Flags().StringVar(&stepConfig.DataMapTags, "dataMapTags", os.Getenv("PIPER_dataMapTags"), "Map of tags for each measurements. It has to be a JSON string. For example: {'series_1':{'tag_a':'a','tag_b':'b'},'series_2':{'tag_c':'c','tag_d':'d'}}")
cmd.MarkFlagRequired("serverUrl")
cmd.MarkFlagRequired("authToken")
cmd.MarkFlagRequired("dataMap")
}
// retrieve step metadata
func influxWriteDataMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "influxWriteData",
Aliases: []config.Alias{},
Description: "Writes metrics to influxdb",
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Secrets: []config.StepSecrets{
{Name: "influxAuthTokenId", Description: "Influxdb token for authentication to the InfluxDB. In 1.8 version use 'username:password' instead.", Type: "jenkins"},
},
Parameters: []config.StepParameters{
{
Name: "serverUrl",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_serverUrl"),
},
{
Name: "authToken",
ResourceRef: []config.ResourceReference{
{
Name: "influxAuthTokenId",
Type: "secret",
},
{
Name: "",
Paths: []string{"$(vaultPath)/influxdb", "$(vaultBasePath)/$(vaultPipelineName)/influxdb", "$(vaultBasePath)/GROUP-SECRETS/influxdb"},
Type: "vaultSecret",
},
},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_authToken"),
},
{
Name: "bucket",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: `piper`,
},
{
Name: "organization",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_organization"),
},
{
Name: "dataMap",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_dataMap"),
},
{
Name: "dataMapTags",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_dataMapTags"),
},
},
},
},
}
return theMetaData
}

View File

@ -0,0 +1,17 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestInfluxWriteDataCommand(t *testing.T) {
t.Parallel()
testCmd := InfluxWriteDataCommand()
// only high level testing performed - details are tested in step generation procedure
assert.Equal(t, "influxWriteData", testCmd.Use, "command name incorrect")
}

View File

@ -0,0 +1,77 @@
package cmd
import (
"errors"
"testing"
"github.com/SAP/jenkins-library/pkg/influx/mocks"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestWriteData(t *testing.T) {
options := &influxWriteDataOptions{
ServerURL: "http://localhost:8086",
AuthToken: "authToken",
Bucket: "piper",
Organization: "org",
}
errString := "some error"
errWriteData := errors.New(errString)
tests := []struct {
name string
dataMap string
dataMapTags string
writeDataErr error
errExpected bool
errIncludeStr string
}{
{
"Test writing metrics with correct json data - success",
`{"series_1": {"field_a": 11, "field_b": 12}, "series_2": {"field_c": 21, "field_d": 22}}`,
`{"series_1": {"tag_a": "a", "tag_b": "b"}, "series_2": {"tag_c": "c", "tag_d": "d"}}`,
nil,
false,
"",
},
{
"Test writing metrics with invalid dataMap",
`"series_1": {"field_a": 11, "field_b": 12}, "series_2": {"field_c": 21, "field_d": 22}`,
`{"series_1": {"tag_a": "a", "tag_b": "b"}, "series_2": {"tag_c": "c", "tag_d": "d"}}`,
nil,
false,
"Failed to unmarshal dataMap:",
},
{
"Test writing metrics with invalid dataMapTags",
`{"series_1": {"field_a": 11, "field_b": 12}, "series_2": {"field_c": 21, "field_d": 22}}`,
`{"series_1": {"tag_a": 2, "tag_b": "b"}, "series_2": {"tag_c": "c", "tag_d": "d"}}`,
nil,
false,
"Failed to unmarshal dataMapTags:",
},
{
"Test writing metrics with correct json data - failed",
`{"series_1": {"field_a": 11, "field_b": 12}, "series_2": {"field_c": 21, "field_d": 22}}`,
`{"series_1": {"tag_a": "a", "tag_b": "b"}, "series_2": {"tag_c": "c", "tag_d": "d"}}`,
errWriteData,
true,
errString,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
influxClientMock := &mocks.Client{}
writeAPIBlockingMock := &mocks.WriteAPIBlocking{}
writeAPIBlockingMock.On("WritePoint", mock.Anything, mock.Anything).Return(tt.writeDataErr)
influxClientMock.On("WriteAPIBlocking", mock.Anything, mock.Anything).Return(writeAPIBlockingMock)
options.DataMap = tt.dataMap
options.DataMapTags = tt.dataMapTags
err := writeData(options, influxClientMock)
if err != nil {
assert.Contains(t, err.Error(), tt.errIncludeStr)
}
})
}
}

View File

@ -47,6 +47,7 @@ func GetAllStepMetadata() map[string]config.StepData {
"githubSetCommitStatus": githubSetCommitStatusMetadata(),
"gitopsUpdateDeployment": gitopsUpdateDeploymentMetadata(),
"hadolintExecute": hadolintExecuteMetadata(),
"influxWriteData": influxWriteDataMetadata(),
"integrationArtifactDeploy": integrationArtifactDeployMetadata(),
"integrationArtifactDownload": integrationArtifactDownloadMetadata(),
"integrationArtifactGetMplStatus": integrationArtifactGetMplStatusMetadata(),

View File

@ -156,6 +156,7 @@ func Execute() {
rootCmd.AddCommand(TransportRequestReqIDFromGitCommand())
rootCmd.AddCommand(WritePipelineEnv())
rootCmd.AddCommand(ReadPipelineEnv())
rootCmd.AddCommand(InfluxWriteDataCommand())
addRootFlags(rootCmd)
if err := rootCmd.Execute(); err != nil {

1
go.mod
View File

@ -31,6 +31,7 @@ require (
github.com/hashicorp/vault/api v1.1.0
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.11 // indirect
github.com/influxdata/influxdb-client-go/v2 v2.4.0
github.com/jarcoal/httpmock v1.0.8
github.com/magiconair/properties v1.8.4
github.com/magicsong/color-glog v0.0.1 // indirect

29
go.sum
View File

@ -327,10 +327,13 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/deepmap/oapi-codegen v1.6.0 h1:w/d1ntwh91XI0b/8ja7+u5SvA4IFfM0UNNLmiDR1gg0=
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg=
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/denverdino/aliyungo v0.0.0-20170926055100-d3308649c661 h1:lrWnAyy/F72MbxIxFUzKmcMCdt9Oi8RzpAxzTNQHD7o=
@ -428,6 +431,7 @@ github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7/go.mod h1:GeIq9qoE
github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56 h1:VzbudKn/nvxYKOdzgkEBS6SSreRjAgoJ+ZeS4wPFkgc=
github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w=
github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getsentry/sentry-go v0.7.0 h1:MR2yfR4vFfv/2+iBuSnkdQwVg7N9cJzihZ6KJu7srwQ=
github.com/getsentry/sentry-go v0.7.0/go.mod h1:pLFpD2Y5RHIKF9Bw3KH6/68DeN2K/XBJd8awjdPnUwg=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
@ -447,6 +451,7 @@ github.com/go-asn1-ber/asn1-ber v1.4.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkPro
github.com/go-asn1-ber/asn1-ber v1.5.1 h1:pDbRAunXzIUXfx4CB2QJFv5IuPiuoW+sWvr/Us009o8=
github.com/go-asn1-ber/asn1-ber v1.5.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4=
@ -499,8 +504,9 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
@ -651,6 +657,7 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
github.com/gomodule/redigo v1.7.1-0.20190724094224-574c33c3df38/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
@ -715,8 +722,9 @@ github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b0
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ=
@ -949,7 +957,11 @@ github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NH
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v0.0.0-20190411212539-d24b7ba8c4c4 h1:3K3KcD4S6/Y2hevi70EzUTNKOS3cryQyhUnkjE6Tz0w=
github.com/influxdata/influxdb v0.0.0-20190411212539-d24b7ba8c4c4/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI=
github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0=
github.com/iris-contrib/i18n v0.0.0-20171121225848-987a633949d0/go.mod h1:pMCz62A0xJL6I+umB2YTlFRwWXaDFA0jy+5HzGiJjqI=
@ -1054,6 +1066,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.1.11/go.mod h1:i541M3Fj6f76NZtHSj7TXnyM8n2gaodfvfxNnFqi74g=
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk=
@ -1087,6 +1100,7 @@ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsI
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw=
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@ -1464,6 +1478,7 @@ github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKn
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c=
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
@ -1660,8 +1675,9 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81R
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201002202402-0a1ea396d57c/go.mod h1:iQL9McJNjoIa5mjH6nYTCTZXUN6RP+XW3eib7Ya3XcI=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190130055435-99b60b757ec1/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1686,8 +1702,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cO
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -1702,8 +1719,10 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180810170437-e96c4e24768d/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@ -0,0 +1,92 @@
// +build integration
// can be execute with go test -tags=integration ./integration/...
package main
import (
"context"
"fmt"
"testing"
"github.com/SAP/jenkins-library/pkg/influx"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
"github.com/stretchr/testify/assert"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
)
func TestWriteMetrics(t *testing.T) {
t.Parallel()
ctx := context.Background()
const authToken = "influx-token"
const username = "username"
const password = "password"
const bucket = "piper"
const organization = "org"
req := testcontainers.GenericContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
AlwaysPullImage: true,
Image: "influxdb:2.0",
ExposedPorts: []string{"8086/tcp"},
Env: map[string]string{
"DOCKER_INFLUXDB_INIT_MODE": "setup",
"DOCKER_INFLUXDB_INIT_USERNAME": username,
"DOCKER_INFLUXDB_INIT_PASSWORD": password,
"DOCKER_INFLUXDB_INIT_ORG": organization,
"DOCKER_INFLUXDB_INIT_BUCKET": bucket,
"DOCKER_INFLUXDB_INIT_ADMIN_TOKEN": authToken,
},
WaitingFor: wait.ForListeningPort("8086/tcp"),
},
Started: true,
}
influxContainer, err := testcontainers.GenericContainer(ctx, req)
assert.NoError(t, err)
defer influxContainer.Terminate(ctx)
ip, err := influxContainer.Host(ctx)
assert.NoError(t, err)
port, err := influxContainer.MappedPort(ctx, "8086")
host := fmt.Sprintf("http://%s:%s", ip, port.Port())
dataMap := map[string]map[string]interface{}{
"series_1": {"field_a": 11, "field_b": 12},
"series_2": {"field_c": 21, "field_d": 22},
}
dataMapTags := map[string]map[string]string{
"series_1": {"tag_a": "a", "tag_b": "b"},
"series_2": {"tag_c": "c", "tag_d": "d"},
}
influxClient := influxdb2.NewClient(host, authToken)
defer influxClient.Close()
client := influx.NewClient(influxClient, organization, bucket)
err = client.WriteMetrics(dataMap, dataMapTags)
assert.NoError(t, err)
queryAPI := influxClient.QueryAPI(organization)
result, err := queryAPI.Query(context.Background(),
`from(bucket:"piper")|> range(start: -1h) |> filter(fn: (r) => r._measurement == "series_1" or r._measurement == "series_2")`)
assert.NoError(t, err)
valuesMap := map[string]map[string]interface{}{}
expectedValuesMap := map[string]map[string]interface{}{
"series_1_field_a": {"_field": "field_a", "_measurement": "series_1", "_value": int64(11), "tag_a": "a", "tag_b": "b"},
"series_1_field_b": {"_field": "field_b", "_measurement": "series_1", "_value": int64(12), "tag_a": "a", "tag_b": "b"},
"series_2_field_c": {"_field": "field_c", "_measurement": "series_2", "_value": int64(21), "tag_c": "c", "tag_d": "d"},
"series_2_field_d": {"_field": "field_d", "_measurement": "series_2", "_value": int64(22), "tag_c": "c", "tag_d": "d"},
}
for result.Next() {
values := result.Record().Values()
measurement := values["_measurement"]
field := values["_field"]
delete(values, "_start")
delete(values, "_stop")
delete(values, "_time")
delete(values, "result")
delete(values, "table")
valuesMap[fmt.Sprintf("%v_%v", measurement, field)] = values
}
assert.NoError(t, result.Err())
assert.Equal(t, len(expectedValuesMap), len(valuesMap))
assert.Equal(t, expectedValuesMap, valuesMap)
}

45
pkg/influx/client.go Normal file
View File

@ -0,0 +1,45 @@
package influx
import (
"context"
"time"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
)
// Client handles communication with InfluxDB
type Client struct {
client influxdb2.Client
ctx context.Context
organization string
bucket string
}
// NewClient instantiates a Client
func NewClient(influxClient influxdb2.Client, organization string, bucket string) *Client {
ctx := context.Background()
client := Client{
client: influxClient,
ctx: ctx,
organization: organization,
bucket: bucket,
}
return &client
}
// WriteMetrics writes metrics to InfluxDB
func (c *Client) WriteMetrics(dataMap map[string]map[string]interface{}, dataMapTags map[string]map[string]string) error {
writeAPI := c.client.WriteAPIBlocking(c.organization, c.bucket)
for measurement, fields := range dataMap {
tags := dataMapTags[measurement]
point := influxdb2.NewPoint(measurement,
tags,
fields,
time.Now())
if err := writeAPI.WritePoint(c.ctx, point); err != nil {
return err
}
}
return nil
}

62
pkg/influx/client_test.go Normal file
View File

@ -0,0 +1,62 @@
package influx
import (
"errors"
"testing"
"github.com/SAP/jenkins-library/pkg/influx/mocks"
"github.com/stretchr/testify/mock"
)
func TestWriteMetrics(t *testing.T) {
errWriteMetrics := errors.New("error")
tests := []struct {
name string
dataMap map[string]map[string]interface{}
dataMapTags map[string]map[string]string
writePointErr error
err error
}{
{
"Test writing metrics - success",
map[string]map[string]interface{}{
"series_1": {"field_a": 11, "field_b": 12},
"series_2": {"field_c": 21, "field_d": 22},
},
map[string]map[string]string{
"series_1": {"tag_a": "a", "tag_b": "b"},
"series_2": {"tag_c": "c", "tag_d": "d"},
},
nil,
nil,
},
{
"Test writing metrics - failed",
map[string]map[string]interface{}{
"series_1": {"field_a": 11, "field_b": 12},
"series_2": {"field_c": 21, "field_d": 22},
},
map[string]map[string]string{
"series_1": {"tag_a": "a", "tag_b": "b"},
"series_2": {"tag_c": "c", "tag_d": "d"},
},
errWriteMetrics,
errWriteMetrics,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
influxClientMock := &mocks.Client{}
client := NewClient(influxClientMock, "org", "piper")
writeAPIBlockingMock := &mocks.WriteAPIBlocking{}
writeAPIBlockingMock.On("WritePoint", client.ctx, mock.Anything).Return(tt.writePointErr)
influxClientMock.On("WriteAPIBlocking", client.organization, client.bucket).Return(writeAPIBlockingMock)
err := client.WriteMetrics(tt.dataMap, tt.dataMapTags)
if err != tt.err {
t.Errorf("\nactual: %q\nexpected: %q\n", err, tt.err)
}
})
}
}

300
pkg/influx/mocks/client.go Normal file
View File

@ -0,0 +1,300 @@
// Code generated by mockery v2.7.4. DO NOT EDIT.
package mocks
import (
context "context"
api "github.com/influxdata/influxdb-client-go/v2/api"
domain "github.com/influxdata/influxdb-client-go/v2/domain"
http "github.com/influxdata/influxdb-client-go/v2/api/http"
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
mock "github.com/stretchr/testify/mock"
)
// Client is an autogenerated mock type for the Client type
type Client struct {
mock.Mock
}
// AuthorizationsAPI provides a mock function with given fields:
func (_m *Client) AuthorizationsAPI() api.AuthorizationsAPI {
ret := _m.Called()
var r0 api.AuthorizationsAPI
if rf, ok := ret.Get(0).(func() api.AuthorizationsAPI); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.AuthorizationsAPI)
}
}
return r0
}
// BucketsAPI provides a mock function with given fields:
func (_m *Client) BucketsAPI() api.BucketsAPI {
ret := _m.Called()
var r0 api.BucketsAPI
if rf, ok := ret.Get(0).(func() api.BucketsAPI); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.BucketsAPI)
}
}
return r0
}
// Close provides a mock function with given fields:
func (_m *Client) Close() {
_m.Called()
}
// DeleteAPI provides a mock function with given fields:
func (_m *Client) DeleteAPI() api.DeleteAPI {
ret := _m.Called()
var r0 api.DeleteAPI
if rf, ok := ret.Get(0).(func() api.DeleteAPI); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.DeleteAPI)
}
}
return r0
}
// HTTPService provides a mock function with given fields:
func (_m *Client) HTTPService() http.Service {
ret := _m.Called()
var r0 http.Service
if rf, ok := ret.Get(0).(func() http.Service); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(http.Service)
}
}
return r0
}
// Health provides a mock function with given fields: ctx
func (_m *Client) Health(ctx context.Context) (*domain.HealthCheck, error) {
ret := _m.Called(ctx)
var r0 *domain.HealthCheck
if rf, ok := ret.Get(0).(func(context.Context) *domain.HealthCheck); ok {
r0 = rf(ctx)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*domain.HealthCheck)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(ctx)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// LabelsAPI provides a mock function with given fields:
func (_m *Client) LabelsAPI() api.LabelsAPI {
ret := _m.Called()
var r0 api.LabelsAPI
if rf, ok := ret.Get(0).(func() api.LabelsAPI); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.LabelsAPI)
}
}
return r0
}
// Options provides a mock function with given fields:
func (_m *Client) Options() *influxdb2.Options {
ret := _m.Called()
var r0 *influxdb2.Options
if rf, ok := ret.Get(0).(func() *influxdb2.Options); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*influxdb2.Options)
}
}
return r0
}
// OrganizationsAPI provides a mock function with given fields:
func (_m *Client) OrganizationsAPI() api.OrganizationsAPI {
ret := _m.Called()
var r0 api.OrganizationsAPI
if rf, ok := ret.Get(0).(func() api.OrganizationsAPI); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.OrganizationsAPI)
}
}
return r0
}
// QueryAPI provides a mock function with given fields: org
func (_m *Client) QueryAPI(org string) api.QueryAPI {
ret := _m.Called(org)
var r0 api.QueryAPI
if rf, ok := ret.Get(0).(func(string) api.QueryAPI); ok {
r0 = rf(org)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.QueryAPI)
}
}
return r0
}
// Ready provides a mock function with given fields: ctx
func (_m *Client) Ready(ctx context.Context) (bool, error) {
ret := _m.Called(ctx)
var r0 bool
if rf, ok := ret.Get(0).(func(context.Context) bool); ok {
r0 = rf(ctx)
} else {
r0 = ret.Get(0).(bool)
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(ctx)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// ServerURL provides a mock function with given fields:
func (_m *Client) ServerURL() string {
ret := _m.Called()
var r0 string
if rf, ok := ret.Get(0).(func() string); ok {
r0 = rf()
} else {
r0 = ret.Get(0).(string)
}
return r0
}
// Setup provides a mock function with given fields: ctx, username, password, org, bucket, retentionPeriodHours
func (_m *Client) Setup(ctx context.Context, username string, password string, org string, bucket string, retentionPeriodHours int) (*domain.OnboardingResponse, error) {
ret := _m.Called(ctx, username, password, org, bucket, retentionPeriodHours)
var r0 *domain.OnboardingResponse
if rf, ok := ret.Get(0).(func(context.Context, string, string, string, string, int) *domain.OnboardingResponse); ok {
r0 = rf(ctx, username, password, org, bucket, retentionPeriodHours)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*domain.OnboardingResponse)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, string, string, string, string, int) error); ok {
r1 = rf(ctx, username, password, org, bucket, retentionPeriodHours)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// TasksAPI provides a mock function with given fields:
func (_m *Client) TasksAPI() api.TasksAPI {
ret := _m.Called()
var r0 api.TasksAPI
if rf, ok := ret.Get(0).(func() api.TasksAPI); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.TasksAPI)
}
}
return r0
}
// UsersAPI provides a mock function with given fields:
func (_m *Client) UsersAPI() api.UsersAPI {
ret := _m.Called()
var r0 api.UsersAPI
if rf, ok := ret.Get(0).(func() api.UsersAPI); ok {
r0 = rf()
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.UsersAPI)
}
}
return r0
}
// WriteAPI provides a mock function with given fields: org, bucket
func (_m *Client) WriteAPI(org string, bucket string) api.WriteAPI {
ret := _m.Called(org, bucket)
var r0 api.WriteAPI
if rf, ok := ret.Get(0).(func(string, string) api.WriteAPI); ok {
r0 = rf(org, bucket)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.WriteAPI)
}
}
return r0
}
// WriteAPIBlocking provides a mock function with given fields: org, bucket
func (_m *Client) WriteAPIBlocking(org string, bucket string) api.WriteAPIBlocking {
ret := _m.Called(org, bucket)
var r0 api.WriteAPIBlocking
if rf, ok := ret.Get(0).(func(string, string) api.WriteAPIBlocking); ok {
r0 = rf(org, bucket)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(api.WriteAPIBlocking)
}
}
return r0
}

View File

@ -0,0 +1,57 @@
// Code generated by mockery v2.7.4. DO NOT EDIT.
package mocks
import (
context "context"
write "github.com/influxdata/influxdb-client-go/v2/api/write"
mock "github.com/stretchr/testify/mock"
)
// WriteAPIBlocking is an autogenerated mock type for the WriteAPIBlocking type
type WriteAPIBlocking struct {
mock.Mock
}
// WritePoint provides a mock function with given fields: ctx, point
func (_m *WriteAPIBlocking) WritePoint(ctx context.Context, point ...*write.Point) error {
_va := make([]interface{}, len(point))
for _i := range point {
_va[_i] = point[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, ...*write.Point) error); ok {
r0 = rf(ctx, point...)
} else {
r0 = ret.Error(0)
}
return r0
}
// WriteRecord provides a mock function with given fields: ctx, line
func (_m *WriteAPIBlocking) WriteRecord(ctx context.Context, line ...string) error {
_va := make([]interface{}, len(line))
for _i := range line {
_va[_i] = line[_i]
}
var _ca []interface{}
_ca = append(_ca, ctx)
_ca = append(_ca, _va...)
ret := _m.Called(_ca...)
var r0 error
if rf, ok := ret.Get(0).(func(context.Context, ...string) error); ok {
r0 = rf(ctx, line...)
} else {
r0 = ret.Error(0)
}
return r0
}

View File

@ -0,0 +1,73 @@
metadata:
name: influxWriteData
description: Writes metrics to influxdb
longDescription: |
In this step, the metrics are written to the timeseries database [InfluxDB](https://www.influxdata.com/time-series-platform/influxdb/)
spec:
inputs:
secrets:
- name: influxAuthTokenId
description: Influxdb token for authentication to the InfluxDB. In 1.8 version use 'username:password' instead.
type: jenkins
params:
- name: serverUrl
type: string
description: Base URL to the InfluxDB server
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
mandatory: true
- name: authToken
type: string
description: Token to authenticate to the Influxdb
scope:
- PARAMETERS
- STAGES
- STEPS
mandatory: true
secret: true
resourceRef:
- name: influxAuthTokenId
type: secret
- type: vaultSecret
paths:
- $(vaultPath)/influxdb
- $(vaultBasePath)/$(vaultPipelineName)/influxdb
- $(vaultBasePath)/GROUP-SECRETS/influxdb
- name: bucket
type: string
description: Name of database (1.8) or bucket (2.0)
scope:
- PARAMETERS
- STAGES
- STEPS
default: "piper"
- name: organization
type: string
description: Name of influx organization. Only for Influxdb 2.0
scope:
- PARAMETERS
- STAGES
- STEPS
- name: dataMap
type: string
description:
"Map of fields for each measurements. It has to be a JSON string.
For example: {'series_1':{'field_a':11,'field_b':12},'series_2':{'field_c':21,'field_d':22}}"
scope:
- PARAMETERS
- STAGES
- STEPS
mandatory: true
- name: dataMapTags
type: string
description:
"Map of tags for each measurements. It has to be a JSON string.
For example: {'series_1':{'tag_a':'a','tag_b':'b'},'series_2':{'tag_c':'c','tag_d':'d'}}"
scope:
- PARAMETERS
- STAGES
- STEPS
mandatory: false