Skip to content
Snippets Groups Projects
Commit 07787d2c authored by Pierre Smeyers's avatar Pierre Smeyers
Browse files

initial commit

parents
No related branches found
No related tags found
No related merge requests found
.idea/
*.iml
bin/
reports/
include:
- project: 'to-be-continuous/docker'
ref: '1.2.0'
file: '/templates/gitlab-ci-docker.yml'
- project: 'to-be-continuous/golang'
ref: '1.2.0'
file: '/templates/gitlab-ci-golang.yml'
variables:
GO_BUILD_ARGS: "install -tags netgo ./..."
DOCKER_BUILD_ARGS: "--build-arg CI_PROJECT_URL --build-arg TRACKING_CONFIGURATION"
DOCKER_HEALTHCHECK_CONTAINER_ARGS: "--service --skip_tracking my-template-service my-template-version"
stages:
- build
- test
- package-build
- package-test
- acceptance
- publish
# override base jobs not to depend on tracking image
.go-base:
services: []
.docker-base:
services: []
FROM busybox:1.31.0 AS busybox
FROM scratch
ARG CI_PROJECT_URL
ARG TRACKING_CONFIGURATION=""
ENV TRACKING_CONFIGURATION="${TRACKING_CONFIGURATION}"
# hadolint ignore=DL3048
LABEL name="tracking" \
description="Image for tracking 'to be continuous' templates usage"\
url=$CI_PROJECT_URL \
maintainer="tbc-dev@googlegroups.com"
COPY bin/tracking_service /tracking_service
COPY --from=busybox /bin/wget /wget
EXPOSE 80
HEALTHCHECK CMD ["/wget", "-Y", "off", "-O", "-", "http://localhost/health" ]
ENTRYPOINT [ "/tracking_service" ]
CMD [""]
README.md 0 → 100644
# Tracking Probe Service
This project builds a Docker image able to send GitLab CI job information to any Elasticsearch server.
It is aimed at being used in GitLab CI as a [service container](https://docs.gitlab.com/ee/ci/services/)
in order to track _to be continuous_ usage and compute statistics.
## Which information is tracked ?
The _Tracking Probe Service_, whenever added as a [service container](https://docs.gitlab.com/ee/ci/services/)
of a GitLab CI job, will send the following JSON payload to one or several Elasticsearch servers:
```json
{
"@type": "ci-job",
"@timestamp": "2020-10-19T07:34:08Z",
"template": {
"name": "maven",
"version": "1.0.0"
},
"ci": {
"user": {
"id": 6097,
"login": "pismy"
},
"project": {
"id": 23568,
"path": "https://gitlab.com/to-be-continuous/samples/maven-library"
},
"build": {
"ref": "master"
},
"job": {
"id": 8585338,
"name": "mvn-build",
"stage": "package-publish",
"url": "https://gitlab.com/to-be-continuous/samples/maven-library/-/jobs/8585338"
},
"pipeline": {
"id": 1835260,
"url": "https://gitlab.com/to-be-continuous/samples/maven-library/-/pipelines/1835260"
},
"runner": {
"id": 44949,
"description": "shared-runners-manager-4.gitlab.com",
"tags": "gce, east-c, shared, docker, linux, ruby, mysql, postgres, mongo, git-annex",
"version": "13.12.0-rc1"
}
}
}
```
Each of those information are retrieved from [GitLab CI predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html).
From this, you can build any valuable statistics, visualization or so.
## How is it used in GitLab CI ?
The Docker image can be used as a [service container](https://docs.gitlab.com/ee/ci/services/)
in any GitLab CI file as follows:
```yaml
.some-base-job:
services:
- name: "$CI_REGISTRY/to-be-continuous/tools/tracking:master"
command: ["--service", "some-template", "1.0.0"]
some-job-build:
stage: build
extends: .some-base-job
script:
- echo "build"
some-job-test:
stage: test
extends: .some-base-job
script:
- echo "test"
```
The 2 arguments passed to the service container are the template **name** and **version** that will be sent with
the JSON payload (the only 2 information that can't be retrieved from [GitLab CI predefined variables](https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)).
:bulb: this is configured in every _to be continuous_ template.
## How to configure the Elasticsearch servers to send to ?
The configuration is defined in JSON and is **built with the Docker image**.
You shall define it as the `TRACKING_CONFIGURATION` CI/CD variable of this project as follows:
```JSON
{
"clients": [
{
"url":"https://elasticsearch-host",
"authentication": {
"username":"tbc-tracking",
"password":"mYp@55w0rd"
},
"timeout":5,
"indexPrefix":"tbc-",
"esMajorVersion":7,
"skipSslVerification":true
}
]
}
```
:bulb: Notice that you may configure **more than one** Elasticsearch server.
Then manually start a pipeline on the `master` branch: this will (re)generate a new Docker image with your
configuration that will now be used by every template job.
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package internal
import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"time"
)
type Authentication struct {
Username string `json:"username"`
Password string `json:"password"`
}
type ClientTracking struct {
Url string `json:"url"`
IndexPrefix string `json:"indexPrefix"`
ESMajorVersion int `json:"esMajorVersion"`
Authentication *Authentication `json:"authentication"`
Timeout time.Duration `json:"timeout"`
SkipSslVerification bool `json:"skipSslVerification"`
}
func handleProxy() {
log.Printf("'http_proxy' set to '%s'\n", os.Getenv("http_proxy"))
log.Printf("'https_proxy' set to '%s'\n", os.Getenv("https_proxy"))
log.Printf("'no_proxy' set to '%s'\n", os.Getenv("no_proxy"))
}
func init() {
handleProxy()
}
func (client *ClientTracking) buildRequest(message *Message) (error, *http.Request) {
var index, url string
if client.IndexPrefix != "" {
index = fmt.Sprintf("%s%d%02d", client.IndexPrefix, time.Now().Year(), time.Now().Month())
} else {
index = fmt.Sprintf("p19032_data_%d%02d", time.Now().Year(), time.Now().Month())
}
if client.ESMajorVersion >= 7 {
url = fmt.Sprintf("%s/%s/_doc/", client.Url, index)
} else {
url = fmt.Sprintf("%s/%s/event", client.Url, index)
}
if payload, err := json.Marshal(*message); err != nil {
return err, nil
} else if request, err := http.NewRequest("POST", url, bytes.NewBuffer(payload)); err != nil {
return err, nil
} else {
if client.Authentication != nil {
request.SetBasicAuth(client.Authentication.Username, client.Authentication.Password)
}
request.Header.Set("Content-Type", "application/json")
return err, request
}
}
func (client *ClientTracking) sendRequest(request *http.Request) error {
httpClient := &http.Client{}
if client.Timeout != 0 {
httpClient.Timeout = client.Timeout * time.Second
}
if response, err := httpClient.Do(request); err != nil {
return err
} else if (response.StatusCode / 100) != 2 {
return fmt.Errorf("invalid status code %d", response.StatusCode)
} else {
return nil
}
}
func (client *ClientTracking) SendTracking(message *Message) error {
if client.SkipSslVerification {
// nolint
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
}
if err, request := client.buildRequest(message); err != nil {
log.Printf("Error while building request %+v\n", *message)
return err
} else if err := client.sendRequest(request); err != nil {
log.Printf("Error while sending %+v\n", *message)
return err
} else {
log.Printf("Message sent: %+v\n", *message)
return nil
}
}
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package internal
import (
"fmt"
"testing"
"time"
)
func TestBuildRequest(t *testing.T) {
index := fmt.Sprintf("p19032_data_%d%02d", time.Now().Year(), time.Now().Month())
client := ClientTracking{
Url: "http://es-url",
Authentication: &Authentication{
Username: "username",
Password: "P@ssW0rd!",
},
Timeout: time.Duration(5),
SkipSslVerification: true,
}
if err, request := client.buildRequest(&Message{
MessageType: "example",
Timestamp: "1981-01-17T19:45:00Z",
TemplateDescription: TemplateDescription{"example", "6.6.6"},
CiInformation: CiInformation{
User: CiUser{
Id: 111,
Login: "buce8373",
},
Project: CiProject{
Id: 222,
Path: "/project",
},
Build: CiBuild{CommitReference: "commit-id"},
Job: CiJob{
Id: 333,
Name: "job-id",
Stage: "build",
Url: "http://job-url/path",
},
Pipeline: CiPipeline{Id: 444, Url: "http://pipeline-url.com"},
Runner: CiRunner{
Id: 555,
Description: "the runner",
Tags: "docker;shared",
Version: "7.7.7",
},
},
}); err != nil {
t.Fatal(err)
} else if request.URL.Path != fmt.Sprintf("/%s/event", index) {
t.Fatalf("Invalid path: %s", request.URL.Path)
} else if request.Header.Get("Content-Type") != "application/json" {
t.Fatalf("Invalid content type: %s", request.Header.Get("Content-Type"))
} else if request.Header.Get("Authorization") == "" {
t.Fatalf("Authorization not set")
}
}
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package internal
import (
"encoding/json"
"fmt"
"log"
"net/http"
"strings"
)
type healthResponse struct {
Status string `json:"status"`
}
func serverHandler(writer http.ResponseWriter, request *http.Request) {
if strings.ToUpper(request.Method) != "GET" {
http.Error(writer, "Method not allowed", http.StatusMethodNotAllowed)
} else if request.URL.Path != "/health" {
http.Error(writer, fmt.Sprintf("Not found: %s", request.RequestURI), http.StatusNotFound)
} else {
health(writer, request)
}
}
func health(writer http.ResponseWriter, request *http.Request) {
body, err := json.Marshal(healthResponse{Status: "OK"})
if err != nil {
http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
writer.Header().Set("Content-Type", "application/json")
writer.WriteHeader(http.StatusOK)
if _, err = writer.Write(body); err != nil {
panic("Error while sending response in health")
}
}
func HealthService(port int) (error, *http.Server) {
log.Printf("Starting application on port %d\n", port)
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: http.HandlerFunc(serverHandler)}
return server.ListenAndServe(), server
}
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package internal
import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
)
const port = 8080
func TestHealth(t *testing.T) {
url := fmt.Sprintf("http://localhost:%d/health", port)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
t.Fatal(err)
}
res := httptest.NewRecorder()
serverHandler(res, req)
if res.Code != http.StatusOK {
t.Fatalf("Response code was %v - %s", res.Code, res.Body.String())
}
var healthResponse healthResponse
expectedErrorStatus := "OK"
if err := json.Unmarshal(res.Body.Bytes(), &healthResponse); err != nil {
t.Fatal(err)
} else if healthResponse.Status != expectedErrorStatus {
t.Fatalf("Invalid error status. Expected %s, got %s", expectedErrorStatus, healthResponse.Status)
}
}
func TestNotFound(t *testing.T) {
// nolint
paths := []string{"/", "", "/health/other", "/elsewhere"}
for _, path := range paths {
url := fmt.Sprintf("http://localhost:%d%s", port, path)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
t.Fatal(err)
}
res := httptest.NewRecorder()
serverHandler(res, req)
if res.Code != http.StatusNotFound {
t.Fatalf("Response code was %v and should be %d for %s", res.Code, http.StatusNotFound, path)
}
}
}
func TestMethodNotAllowed(t *testing.T) {
url := fmt.Sprintf("http://localhost:%d/health", port)
methods := []string{"POST", "PATCH", "HEAD", "DELETE"}
for _, method := range methods {
req, err := http.NewRequest(method, url, nil)
if err != nil {
t.Fatal(err)
}
res := httptest.NewRecorder()
serverHandler(res, req)
if res.Code != http.StatusMethodNotAllowed {
t.Fatalf("Response code was %v for method %s and should be %d", res.Code, method, http.StatusMethodNotAllowed)
}
}
}
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package internal
import (
"fmt"
"os"
"strconv"
"strings"
"time"
)
type TemplateDescription struct {
Name string `json:"name"`
Version string `json:"version"`
}
type CiId int
type Timestamp string
func CurrentTimestamp() Timestamp {
return Timestamp(strings.ReplaceAll(fmt.Sprintln(time.Now().UTC().Format("2006-01-02T15:04:05Z")), "\n", ""))
}
type CiUser struct {
Id CiId `json:"id"`
Login string `json:"login"`
}
type CiProject struct {
Id CiId `json:"id"`
Path string `json:"path"`
}
type CiBuild struct {
CommitReference string `json:"ref"`
}
type CiJob struct {
Id CiId `json:"id"`
Name string `json:"name"`
Stage string `json:"stage"`
Url string `json:"url"`
}
type CiPipeline struct {
Id CiId `json:"id"`
Url string `json:"url"`
}
type CiRunner struct {
Id CiId `json:"id"`
Description string `json:"description"`
Tags string `json:"tags"`
Version string `json:"version"`
}
type CiInformation struct {
User CiUser `json:"user"`
Project CiProject `json:"project"`
Build CiBuild `json:"build"`
Job CiJob `json:"job"`
Pipeline CiPipeline `json:"pipeline"`
Runner CiRunner `json:"runner"`
}
type Message struct {
MessageType string `json:"@type"`
Timestamp Timestamp `json:"@timestamp"`
TemplateDescription TemplateDescription `json:"template"`
CiInformation CiInformation `json:"ci"`
}
func getCiIdFromEnv(variable string) CiId {
if id, err := strconv.Atoi(os.Getenv(variable)); err != nil {
return CiId(-1)
} else {
return CiId(id)
}
}
func getStringFromEnv(variable string) string {
return os.Getenv(variable)
}
func CiTrackingMessage(templateName string, version string) *Message {
return &Message{
MessageType: "ci-job",
Timestamp: CurrentTimestamp(),
TemplateDescription: TemplateDescription{
Name: templateName,
Version: version},
CiInformation: CiInformation{
User: CiUser{
Id: getCiIdFromEnv("GITLAB_USER_ID"),
Login: getStringFromEnv("GITLAB_USER_LOGIN")},
Project: CiProject{
Id: getCiIdFromEnv("CI_PROJECT_ID"),
Path: getStringFromEnv("CI_PROJECT_PATH")},
Build: CiBuild{
CommitReference: getStringFromEnv("CI_COMMIT_REF_NAME")},
Job: CiJob{
Id: getCiIdFromEnv("CI_JOB_ID"),
Name: getStringFromEnv("CI_JOB_NAME"),
Stage: getStringFromEnv("CI_JOB_STAGE"),
Url: getStringFromEnv("CI_JOB_URL")},
Pipeline: CiPipeline{
Id: getCiIdFromEnv("CI_PIPELINE_ID"),
Url: getStringFromEnv("CI_PIPELINE_URL")},
Runner: CiRunner{
Id: getCiIdFromEnv("CI_RUNNER_ID"),
Description: getStringFromEnv("CI_RUNNER_DESCRIPTION"),
Tags: getStringFromEnv("CI_RUNNER_TAGS"),
Version: getStringFromEnv("CI_RUNNER_VERSION")},
},
}
}
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package internal
import (
"bytes"
"encoding/json"
"strings"
"testing"
)
func Test_message_json_encoded(t *testing.T) {
expected := []byte(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(`{
"@type":"ci-job",
"@timestamp":"2019-10-27T09:57:31Z",
"template":{"name":"Test","version":"0.1.0"},
"ci":{
"user":{"id":666,"login":"mmmm1998"},
"project":{"id":333,"path":"https://gitlab.com/example/project.git"},
"build":{"ref":"reference"},
"job":{"id":888,"name":"test-job","stage":"check","url":"https://gitlab.com/example/project/jobs/888"},
"pipeline":{"id":999,"url":"https://gitlab.com/example/project/pipelines/999"},
"runner":{"id":111,"description":"My fabulous runner","tags":"fabulous","version":"1"}
}
}`, "\n", ""), "\t", ""), " ", ""))
message := Message{MessageType: "ci-job",
Timestamp: Timestamp("2019-10-27T09:57:31Z"),
TemplateDescription: TemplateDescription{Name: "Test", Version: "0.1.0"},
CiInformation: CiInformation{User: CiUser{Id: 666, Login: "mmmm1998"},
Project: CiProject{
Id: 333,
Path: "https://gitlab.com/example/project.git",
},
Build: CiBuild{CommitReference: "reference"},
Job: CiJob{
Id: 888,
Name: "test-job",
Stage: "check",
Url: "https://gitlab.com/example/project/jobs/888",
},
Pipeline: CiPipeline{
Id: 999,
Url: "https://gitlab.com/example/project/pipelines/999",
},
Runner: CiRunner{
Id: 111,
Description: "My fabulous runner",
Tags: "fabulous",
Version: "1",
}}}
if result, err := json.Marshal(message); err != nil {
t.Fatalf("Error while serializing message: %v", err)
} else if !bytes.Equal(expected, result) {
t.Fatalf("Encoding error\nExpected:\n%s\nGot:\n%s", string(expected), string(result))
}
}
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"log"
"os"
. "tbc.orange.com/gitlab-templates-tracking/cmd/tracking_service/internal"
)
const PORT = 80
type Configuration struct {
Clients []ClientTracking `json:"clients"`
}
type runEnvironment struct {
service bool
skipTracking bool
port int
template string
version string
}
func readConfigurationFromEnv() (Configuration, error) {
config := os.Getenv("TRACKING_CONFIGURATION")
if config != "" {
return readConfiguration([]byte(config))
}
return Configuration{}, nil
}
func readConfiguration(config []byte) (Configuration, error) {
var conf Configuration
if config != nil {
err := json.Unmarshal(config, &conf)
return conf, err
}
return conf, nil
}
func readArguments(program string, args []string) (error, *runEnvironment) {
var usage bytes.Buffer
fs := flag.NewFlagSet(program, flag.ExitOnError)
service := fs.Bool("service", false, "Launch send tracking as a service")
skipTracking := fs.Bool("skip_tracking", false, "Does not send tracking")
port := fs.Int("port", PORT, "Service port")
fs.SetOutput(&usage)
if err := fs.Parse(args); err != nil {
fs.Usage()
return fmt.Errorf(usage.String()), nil
} else if fs.NArg() != 2 {
usage.Write([]byte(fmt.Sprintf("%s: specify template name and version\n", program)))
fs.Usage()
return fmt.Errorf(usage.String()), nil
}
return nil, &runEnvironment{service: *service, skipTracking: *skipTracking, port: *port, template: fs.Arg(0), version: fs.Arg(1)}
}
func main() {
var arguments []string
if len(os.Args) == 1 {
arguments = []string{}
} else {
arguments = os.Args[1:]
}
err, environment := readArguments(os.Args[0], arguments)
if err != nil {
_, _ = fmt.Fprint(os.Stderr, err)
os.Exit(1)
}
config, err := readConfigurationFromEnv()
if err != nil {
_, _ = fmt.Fprint(os.Stderr, err)
os.Exit(2)
}
if !environment.skipTracking {
log.Printf("Sending tracking for %s %s\n", environment.template, environment.version)
for _, client := range config.Clients {
if err := client.SendTracking(CiTrackingMessage(environment.template, environment.version)); err != nil {
log.Println(err)
} else {
log.Println("Tracking sent")
}
}
} else {
log.Println("Skip send tracking")
}
if !environment.service {
log.Println("Service not launched")
} else {
log.Printf("Launching service on port %d\n", environment.port)
if err, server := HealthService(environment.port); err != nil {
panic(err)
} else {
defer server.Close()
}
}
}
/*
* Copyright (C) 2021 Orange & contributors
*
* This program is free software; you can redistribute it and/or modify it under the terms
*
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301, USA.
*/
package main
import (
"testing"
"time"
. "tbc.orange.com/gitlab-templates-tracking/cmd/tracking_service/internal"
)
func TestBuildClient(t *testing.T) {
configurations := "{\"clients\": [{\"url\": \"http://somewhere.com\",\"authentication\": {\"username\": \"username\",\"password\": \"p@ssw0rd!\"},\"timeout\": 5,\"indexPrefix\":\"tbc-\",\"esMajorVersion\":7,\"skipSslVerification\": true}]} "
url := "http://somewhere.com"
authentication := Authentication{
Username: "username",
Password: "p@ssw0rd!",
}
timeout := time.Duration(5)
clients, _ := readConfiguration([]byte(configurations))
client := clients.Clients[0]
if client.Authentication.Username != authentication.Username || client.Authentication.Password != authentication.Password {
t.Fatal("Authentication invalid")
} else if client.Timeout != timeout {
t.Fatalf("Invalid timeout. Expected %d got %d", timeout, client.Timeout)
} else if client.Url != url {
t.Fatal("Invalid url")
}
}
func TestReadTemplateAndVersion(t *testing.T) {
if err, arguments := readArguments("test", []string{"--skip_tracking", "template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.template != "template" && arguments.version != "version" {
t.Fatalf("Unexpected template/version got: %s/%s", arguments.template, arguments.version)
}
if err, arguments := readArguments("test", []string{"--port", "8080", "template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.template != "template" && arguments.version != "version" {
t.Fatalf("Unexpected template/version got: %s/%s", arguments.template, arguments.version)
}
if err, arguments := readArguments("test", []string{"--service", "template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.template != "template" && arguments.version != "version" {
t.Fatalf("Unexpected template/version got: %s/%s", arguments.template, arguments.version)
}
if err, arguments := readArguments("test", []string{"--service", "--port", "8080", "--skip_tracking", "template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.template != "template" && arguments.version != "version" {
t.Fatalf("Unexpected template/version got: %s/%s", arguments.template, arguments.version)
}
}
func TestService(t *testing.T) {
if err, arguments := readArguments("test", []string{"--service", "template", "version"}); err != nil {
t.Fatal(err)
} else if !arguments.service {
t.Fatal("Error while loading service flag")
}
if err, arguments := readArguments("test", []string{"template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.service {
t.Fatal("Error while loading service flag")
}
}
func TestSkipTracking(t *testing.T) {
if err, arguments := readArguments("test", []string{"--skip_tracking", "template", "version"}); err != nil {
t.Fatal(err)
} else if !arguments.skipTracking {
t.Fatal("Error while loading skip tracking flag")
}
if err, arguments := readArguments("test", []string{"template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.skipTracking {
t.Fatal("Error while loading skip tracking flag")
}
}
func TestPort(t *testing.T) {
if err, arguments := readArguments("test", []string{"--port", "8080", "template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.port != 8080 {
t.Fatal("Error while reading port")
}
if err, arguments := readArguments("test", []string{"template", "version"}); err != nil {
t.Fatal(err)
} else if arguments.port != PORT {
t.Fatal("Default port should be set if none precised")
}
}
go.mod 0 → 100644
logo.png 0 → 100644
logo.png

15.8 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment