Skip to content

Commit

Permalink
feat: refactor history to be top-level field
Browse files Browse the repository at this point in the history
Signed-off-by: Mark Phelps <[email protected]>
  • Loading branch information
markphelps committed Dec 5, 2024
1 parent cc1099b commit f78bd9b
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 40 deletions.
8 changes: 4 additions & 4 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,17 +196,17 @@ func (c *Config) OCIRepository(name string) (_ *oci.Repository, err error) {
return repo, nil
}

// BoltDB constructs and configures a boltdb instance from configuration.
// FileDB constructs and configures a boltdb instance from configuration.
// It caches built instances and returns the same instance for subsequent
// calls with the same name.
func (c *Config) BoltDB(name string) (*bbolt.DB, error) {
func (c *Config) FileDB(name string) (*bbolt.DB, error) {
if db, ok := c.cache.bolt[name]; ok {
return db, nil
}

conf, ok := c.conf.Sources.Bolt[name]
conf, ok := c.conf.History.File[name]
if !ok {
return nil, fmt.Errorf("bolt %q: configuration not found", name)
return nil, fmt.Errorf("file db %q: configuration not found", name)
}

db, err := bbolt.Open(conf.Path, 0666, nil)
Expand Down
2 changes: 1 addition & 1 deletion docs/_sidebar.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
- [Getting Started](/)
- [Concepts](/concepts.md)
- [Configuration](/configuration.md)
- [Guides](/guides/index.md)
- [Guides](/guides/index.md)
19 changes: 19 additions & 0 deletions docs/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,25 @@ type Edge interface {
}
```

### History

Pipelines can be configured to record the history of resource state transitions in a target phase. This enables a number of features:

- Visualization of resource state transitions in the Glu UI.
- Reversion of resource state to a previous version.
- Triggering of promotion based on the presence of a new version (upcoming feature).
- Pinning of resource versions to prevent them from being overwritten (upcoming feature).

To enable history for a pipeline, you must configure a logging sink for the pipeline.

We currently support a file-based logger, which writes to a database file on the local filesystem.

```go
pipeline.LogsTo(pipelines.FileLogger[*SomeResource]("history"))
```

File-based history is configured in the [configuration file](./configuration.md).

#### Promotion

The core `promotion` kind edge promotes one phase to the next on a call to `Perform(ctx)`.
Expand Down
52 changes: 50 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ sources:
name: origin
url: https://github.com/get-glu/example-app
credential: github # name of the credential (above) to be used for this source

history:
file:
path: /tmp/glu-history.db # path to the file on the local filesystem (optional, defaults to a temporary file)
```
Credentials are used to authenticate with the source. [Sources](/?id=sources) allow for viewing and updating of resources (e.g. git repositories, OCI images).
Expand Down Expand Up @@ -63,7 +67,9 @@ Valid values are `debug`, `info`, `warn`, and `error`.

### credentials

#### `credentials.<name>`
Credentials are used to authenticate with sources. They are referenced by name in the configuration for sources.

#### credentials.\<name\>

The configuration for a named credential.

Expand Down Expand Up @@ -143,7 +149,11 @@ The path to the private key of the GitHub App.

### sources

#### `sources.<name>`
Sources are used to configure resources (e.g. git repositories, OCI images, files on the local filesystem).

Different sources have different configuration options and are configured under a key corresponding to the source type.

#### sources.\<name\>

The configuration for a named source.

Expand Down Expand Up @@ -209,6 +219,24 @@ The reference to the OCI repository.

The name of the credential to use for the OCI repository.

### history

History is used to store the history of the resources and actions performed on them.

#### `history.type`

The type of history to use.

Valid values are `file`. (default)

#### history.file.\<name\>

The configuration for a file history.

#### `history.file.<name>.path`

The path to the file on the local filesystem.

### server

#### `server.port`
Expand All @@ -232,3 +260,23 @@ The path to the certificate file to use for HTTPS.
#### `server.key_file`

The path to the key file to use for HTTPS.

### metrics

#### `metrics.enabled`

Whether to enable metrics collection.

#### `metrics.exporter`

The exporter to use for metrics collection. Defaults to `prometheus`.

Valid values are `prometheus` and `otlp`.

#### `metrics.otlp.endpoint`

The endpoint to use for OTLP metrics collection.

#### `metrics.otlp.headers`

Additional headers to use for OTLP metrics collection. This can be used to add authentication headers, etc.
6 changes: 3 additions & 3 deletions docs/guides/_sidebar.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
* Glu and GitOps
* [Overview](/guides/gitops-overview.md)
* [Implementation](/guides/gitops-implementation.md)
- Glu and GitOps
- [Overview](/guides/gitops-overview.md)
- [Implementation](/guides/gitops-implementation.md)
5 changes: 2 additions & 3 deletions docs/guides/gitops-implementation.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
GitOps and Glu: Implementation
==============================
# GitOps and Glu: Implementation

This guide follows on from the previous [GitOps and Glu: Overview](/guides/gitops-overview.md) guide.

Expand Down Expand Up @@ -412,7 +411,7 @@ func (r *AppResource) WriteTo(ctx context.Context, phase glu.Descriptor, fs fs.F
}
defer fi.Close()
// re-encode the deployment and copy it into the file
data, err := yaml.Marshal(deployment)
if err != nil {
Expand Down
3 changes: 1 addition & 2 deletions docs/guides/gitops-overview.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
GitOps and Glu: Overview
========================
# GitOps and Glu: Overview

In this guide, we will create a GitOps pipeline for deploying some simple applications to multiple "environments".
For the purposes of keeping the illustration simple to create (and destroy), our environments are simply two separate pods in the same cluster. However, Glu can extend to multiple namespaces, clusters, or even non-Kubernetes deployment environments.
Expand Down
3 changes: 1 addition & 2 deletions docs/guides/index.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
Guides
======
# Guides

This section contains guides for exploring pre-built Glu pipelines in action.

Expand Down
2 changes: 1 addition & 1 deletion examples/oci-and-git/experiment.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func run(ctx context.Context) error {
system := glu.NewSystem(ctx, glu.Name("mypipelines"), glu.WithUI(ui.FS()))
if err := pipelines.NewBuilder(system, glu.Name("checkout"), NewCheckoutResource).
// configure a phase logging sink called history
LogsTo(pipelines.BoltLogger[*CheckoutResource]("history")).
LogsTo(pipelines.FileLogger[*CheckoutResource]("history")).
// fetch the configured OCI repositority source named "checkout"
NewPhase(pipelines.OCIPhase[*CheckoutResource](glu.Name("oci"), "checkout")).
// build a phase for the staging environment which source from the git repository
Expand Down
6 changes: 3 additions & 3 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ type Config struct {
Sources Sources `glu:"sources"`
Server Server `glu:"server"`
Metrics Metrics `glu:"metrics"`
History History `glu:"history"`
}

type Sources struct {
Git GitSources `glu:"git"`
OCI OCISources `glu:"oci"`
Bolt BoltDBs `glu:"bolt"`
Git GitSources `glu:"git"`
OCI OCISources `glu:"oci"`
}

type defaulter interface {
Expand Down
10 changes: 6 additions & 4 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,14 @@ func TestConfig(t *testing.T) {
},
},
{
path: "testdata/bolt/default",
path: "testdata/history/file/default",
expected: &Config{
Log: Log{Level: "info"},
Sources: Sources{
Bolt: BoltDBs{
"default": &BoltDB{
History: History{
Type: HistoryTypeFile,
File: FileDBs{
"default": &FileDB{
Name: "history",
Path: "history.db",
},
},
Expand Down
39 changes: 29 additions & 10 deletions pkg/config/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,55 @@ import (
"os"
)

type BoltDBs map[string]*BoltDB
type HistoryType string

func (b BoltDBs) validate() error {
const (
HistoryTypeFile HistoryType = "file"
)

type History struct {
Type HistoryType `glu:"type"`
File FileDBs `glu:"file"`
}

func (h *History) setDefaults() error {
if h.Type == "" {
h.Type = HistoryTypeFile
}

return nil
}

type FileDBs map[string]*FileDB

func (b FileDBs) validate() error {
for name, source := range b {
if err := source.validate(); err != nil {
return fmt.Errorf("bolt %q: %w", name, err)
return fmt.Errorf("file db %q: %w", name, err)
}
}

return nil
}

func (b BoltDBs) setDefaults() error {
func (b FileDBs) setDefaults() error {
for name, source := range b {
if err := source.setDefaults(name); err != nil {
return fmt.Errorf("bolt %q: %w", name, err)
return fmt.Errorf("file db %q: %w", name, err)
}
}

return nil
}

type BoltDB struct {
type FileDB struct {
Name string `glu:"name"`
Path string `glu:"path"`
}

func (s *BoltDB) validate() error {
func (s *FileDB) validate() error {
if s == nil {
return errFieldRequired("bolt")
return errFieldRequired("file")
}

if s.Path == "" {
Expand All @@ -45,7 +64,7 @@ func (s *BoltDB) validate() error {
return nil
}

func (s *BoltDB) setDefaults(name string) error {
func (s *FileDB) setDefaults(name string) error {
if s == nil {
return nil
}
Expand All @@ -62,7 +81,7 @@ func (s *BoltDB) setDefaults(name string) error {

s.Path = fi.Name()

slog.Info("created temporary file for bolt", "source.bolt", name, "path", s.Path)
slog.Info("created temporary file for file db", "history.file", name, "path", s.Path)
}

return nil
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
sources:
bolt:
history:
type: file
file:
default:
path: "history.db"
6 changes: 3 additions & 3 deletions pkg/pipelines/pipelines.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,11 +206,11 @@ func OCIPhase[R srcoci.Resource](meta glu.Metadata, srcName string, opts ...cont
}
}

// BoltLogger returns an instance of type.PhaseLogger which writes to a boltdb file
// FileLogger returns an instance of type.PhaseLogger which writes to a file db
// as configured by the provided name.
func BoltLogger[R glu.Resource](name string) func(Builder[R]) (typed.PhaseLogger[R], error) {
func FileLogger[R glu.Resource](name string) func(Builder[R]) (typed.PhaseLogger[R], error) {
return func(b Builder[R]) (typed.PhaseLogger[R], error) {
db, err := b.Configuration().BoltDB(name)
db, err := b.Configuration().FileDB(name)
if err != nil {
return nil, err
}
Expand Down

0 comments on commit f78bd9b

Please sign in to comment.