Skip to content

Commit

Permalink
feat(parser) add flag to log diff on failure
Browse files Browse the repository at this point in the history
Add a new --log-failed-config flag. When enabled, if the reconciliation
loop encounters an error, perform a diff against the last known good
configuration and write it to a temporary file.
  • Loading branch information
Travis Raines committed Dec 18, 2020
1 parent 87a4ab5 commit 2e61ef3
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 3 deletions.
6 changes: 4 additions & 2 deletions cli/ingress-controller/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ type cliConfig struct {
EnableReverseSync bool

// Logging
LogLevel string
LogFormat string
LogLevel string
LogFormat string
LogFailedConfig bool

// k8s connection details
APIServerHost string
Expand Down Expand Up @@ -310,6 +311,7 @@ func parseFlags() (cliConfig, error) {
// Logging
config.LogLevel = viper.GetString("log-level")
config.LogFormat = viper.GetString("log-format")
config.LogFailedConfig = viper.GetBool("log-failed-config")

// k8s connection details
config.APIServerHost = viper.GetString("apiserver-host")
Expand Down
2 changes: 2 additions & 0 deletions cli/ingress-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ func controllerConfigFromCLIConfig(cliConfig cliConfig) controller.Configuration
UpdateStatus: cliConfig.UpdateStatus,
UpdateStatusOnShutdown: cliConfig.UpdateStatusOnShutdown,
ElectionID: cliConfig.ElectionID,

LogFailedConfig: cliConfig.LogFailedConfig,
}
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ require (
github.com/stretchr/testify v1.5.1
github.com/tidwall/gjson v1.2.1
github.com/tidwall/match v1.0.1 // indirect
github.com/yudai/gojsondiff v1.0.0
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208
gopkg.in/go-playground/assert.v1 v1.2.1 // indirect
gopkg.in/go-playground/pool.v3 v3.1.1
Expand Down
12 changes: 11 additions & 1 deletion internal/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package controller
import (
"context"
"fmt"
"io/ioutil"
"sync"
"sync/atomic"
"time"
Expand Down Expand Up @@ -90,7 +91,8 @@ type Configuration struct {

EnableKnativeIngressSupport bool

Logger logrus.FieldLogger
Logger logrus.FieldLogger
LogFailedConfig bool
}

// sync collects all the pieces required to assemble the configuration file and
Expand Down Expand Up @@ -223,6 +225,7 @@ type KongController struct {
backgroundGroup errgroup.Group

runningConfigHash []byte
lastConfig []byte

isShuttingDown uint32

Expand All @@ -231,12 +234,19 @@ type KongController struct {
PluginSchemaStore PluginSchemaStore

Logger logrus.FieldLogger

tmpDir string
}

// Start starts a new master process running in foreground, blocking until the next call to
// Stop.
func (n *KongController) Start() {
n.Logger.Debugf("startin up controller")
var err error
n.tmpDir, err = ioutil.TempDir("", "controller")
if err != nil {
panic(fmt.Errorf("failed to create a temporary working directory: %v", err))
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()
Expand Down
28 changes: 28 additions & 0 deletions internal/ingress/controller/kong.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"crypto/sha256"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"reflect"
"sort"
Expand All @@ -36,8 +37,28 @@ import (
"github.com/kong/go-kong/kong"
"github.com/kong/kubernetes-ingress-controller/internal/ingress/controller/parser/kongstate"
"github.com/kong/kubernetes-ingress-controller/internal/ingress/utils"
"github.com/yudai/gojsondiff"
"github.com/yudai/gojsondiff/formatter"
)

func getDiff(a []byte, b []byte) (string, error) {
differ := gojsondiff.New()
d, err := differ.Compare(a, b)
if err != nil {
return "", err
}
var rightObject map[string]interface{}
err = json.Unmarshal(b, &rightObject)
if err != nil {
return "", err
}

formatter := formatter.NewAsciiFormatter(rightObject,
formatter.AsciiFormatterConfig{})
diffString, err := formatter.Format(d)
return diffString, err
}

// OnUpdate is called periodically by syncQueue to keep the configuration in sync.
// returning nil implies the synchronization finished correctly.
// Returning an error means requeue the update.
Expand Down Expand Up @@ -67,15 +88,22 @@ func (n *KongController) OnUpdate(ctx context.Context, state *kongstate.KongStat
return nil
}
}
target, _ := json.Marshal(targetContent)
if n.cfg.InMemory {
err = n.onUpdateInMemoryMode(ctx, targetContent, customEntities)
} else {
err = n.onUpdateDBMode(targetContent)
}
if err != nil {
if n.cfg.LogFailedConfig {
diff, _ := getDiff(target, n.lastConfig)
_ = ioutil.WriteFile(n.tmpDir+"/target.json", target, 0600)
_ = ioutil.WriteFile(n.tmpDir+"/diff.json", []byte(diff), 0600)
}
return err
}
n.runningConfigHash = shaSum
n.lastConfig = target
n.Logger.Info("successfully synced configuration to kong")
return nil
}
Expand Down

0 comments on commit 2e61ef3

Please sign in to comment.