Skip to content

Commit

Permalink
Writes to insights remote endpoint with in cluster gatherer command
Browse files Browse the repository at this point in the history
* Adds insights remote lib

* Updates arguments

* Removes local token

* Small updates to Facts

* Updates defaults to bring in line with insights-remote

* Completing work on in cluster gathering

* Removes extraneous exit

* Fixes error handling in remote writer

* Refactors token gathering

* Removes test gatherer

---------

Co-authored-by: Chris <[email protected]>
  • Loading branch information
bomoko and CGoodwin90 authored Nov 6, 2023
1 parent bcfc084 commit 6264463
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.13
go-version: ^1.18

- name: Check out code into the Go module directory
uses: actions/checkout@v2
Expand Down
110 changes: 110 additions & 0 deletions cmd/gatherInCluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package cmd

import (
"encoding/json"
"log"
"os"

"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/uselagoon/lagoon-facts-app/gatherers"
)

var tokenValue string
var tokenFile string
var insightsRemoteEndpoint string

// gatherCmd represents the gather command
var gatherInClusterCmd = &cobra.Command{
Use: "gather-in-cluster",
Short: "Running this command will invoke the registered gatherers in cluster",
Long: `Running all the registered gatherers will inspect the system and write FACT data back to the Lagoon insights system via insights-remote`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
//get the basic env vars
if argStatic && argDynamic {
log.Fatalf("Cannot use both 'static' and 'dynamic' only gatherers - exiting")
}
},
Run: func(cmd *cobra.Command, args []string) {

if tokenValue == "" {
if tokenFile == "" {
log.Fatal("Either a token or a token file needs to be passed as an argument")
}
var err error
tokenValue, err = getTokenFromFile(tokenFile)
if err != nil {
log.Fatalf("Unable to load token: %v - %v", tokenFile, err.Error())
}
}

//set gatherer type to be static by default
gathererTypeArg := gatherers.GATHERER_TYPE_STATIC
if argDynamic {
gathererTypeArg = gatherers.GATHERER_TYPE_DYNAMIC
}

//run the gatherers...
gathererSlice := gatherers.GetGatherers()

var facts []gatherers.GatheredFact

for _, e := range gathererSlice {
if e.GetGathererCmdType() == gathererTypeArg {
if e.AppliesToEnvironment() {
gatheredFacts, err := e.GatherFacts()
if err != nil {
log.Println(err.Error())
continue
}
for _, f := range gatheredFacts {
if verbose := viper.Get("verbose"); verbose == true {
log.Printf("Registering %s", f.Name)
}
}
facts = append(facts, gatheredFacts...)
}
}
}

if !dryRun {
err := gatherers.WriteFactsToInsightsRemote(tokenValue, facts)
if err != nil {
log.Println(err.Error())
}
}

if dryRun {
if facts != nil {
log.Println("---- Dry run ----")
log.Printf("Would post the follow facts to '%s:%s'", projectName, environmentName)
s, _ := json.MarshalIndent(facts, "", "\t")
log.Println(string(s))
}
}
},
}

func getTokenFromFile(tokenFile string) (string, error) {
_, err := os.Stat(tokenFile)
if err != nil {
return "", err
}

ba, err := os.ReadFile(tokenFile)
if err != nil {
return "", err
}
return string(ba), nil
}

//var GatherCommand = gatherCmd

func init() {
gatherInClusterCmd.PersistentFlags().StringVarP(&tokenValue, "token", "t", "", "The Lagoon insights remote token")
gatherInClusterCmd.PersistentFlags().StringVarP(&tokenFile, "token-file", "", "/var/run/secrets/lagoon/dynamic/insights-token/INSIGHTS_TOKEN", "Read the Lagoon insights remote token from a file")
gatherInClusterCmd.PersistentFlags().BoolVarP(&dryRun, "dry-run", "d", false, "run gathers and print to screen without running write methods")
gatherInClusterCmd.PersistentFlags().StringVar(&insightsRemoteEndpoint, "insights-remote-endpoint", "http://lagoon-remote-insights-remote.lagoon.svc/facts", "The Lagoon insights remote endpoint")
viper.BindPFlag("insights-remote-endpoint", gatherInClusterCmd.PersistentFlags().Lookup("insights-remote-endpoint"))
rootCmd.AddCommand(gatherInClusterCmd)
}
3 changes: 1 addition & 2 deletions gatherers/graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ package gatherers
import (
"context"
"fmt"
"log"

"github.com/machinebox/graphql"
"github.com/uselagoon/lagoon-facts-app/utils"
"golang.org/x/oauth2"
"log"
)

const lagoonAPIEndpoint = "https://api.lagoon.amazeeio.cloud/graphql"
Expand Down
62 changes: 62 additions & 0 deletions gatherers/insights-remote-writer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package gatherers

import (
"bytes"
"encoding/json"
"fmt"
"github.com/spf13/viper"
insightRemoteLib "github.com/uselagoon/insights-remote-lib"
"io/ioutil"
"log"
"net/http"
)

func WriteFactsToInsightsRemote(token string, facts []GatheredFact) error {

insightsRemoteFacts := insightRemoteLib.Facts{
Facts: []insightRemoteLib.Fact{},
}

for _, fact := range facts {
f := insightRemoteLib.Fact{
Name: fact.Name,
Value: fact.Value,
Source: fact.Source,
Description: fact.Description,
Category: string(fact.Category),
}

insightsRemoteFacts.Facts = append(insightsRemoteFacts.Facts, f)
}

bodyString, err := json.Marshal(insightsRemoteFacts)
if err != nil {
log.Fatal(err.Error())
}

fmt.Printf("Sending %v fact(s) to insights core\n", len(facts))

serviceEndpoint := viper.GetString("insights-remote-endpoint")
req, _ := http.NewRequest(http.MethodPost, serviceEndpoint, bytes.NewBuffer(bodyString))
req.Header.Set("Authorization", token)
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
response, err := client.Do(req)

if err != nil {
return err
}

if response.StatusCode != 200 {
bodyData, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Fatal(err.Error())
}

log.Fatalf("There was an error sending the facts to '%s': %v- %v \n", serviceEndpoint, response.StatusCode, string(bodyData))
}

defer response.Body.Close()

return err
}
2 changes: 1 addition & 1 deletion gatherers/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ func LoadYamlConfig(yamlFilePath string) ([]byte, error) {
return []byte{}, err
}
return data, nil
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/uselagoon/lagoon-facts-app

go 1.13
go 1.18

require (
github.com/machinebox/graphql v0.2.2
Expand Down
6 changes: 6 additions & 0 deletions go.work
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
go 1.18

use (
.
insightRemoteLib
)
3 changes: 3 additions & 0 deletions insightRemoteLib/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/uselagoon/insights-remote-lib

go 1.18
21 changes: 21 additions & 0 deletions insightRemoteLib/remote.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package insightRemoteLib

type Fact struct {
EnvironmentId string `json:"environment"`
ProjectName string `json:"projectName"`
EnvironmentName string `json:"environmentName"`
Name string `json:"name"`
Value string `json:"value"`
Source string `json:"source"`
Description string `json:"description"`
Type string `json:"type"`
Category string `json:"category"`
Service string `json:"service"`
}

type Facts struct {
EnvironmentId int `json:"environment"`
ProjectName string `json:"projectName"`
EnvironmentName string `json:"environmentName"`
Facts []Fact `json:"facts"`
}

0 comments on commit 6264463

Please sign in to comment.