Skip to content

Commit

Permalink
Merge branch 'main' of github.com:opentdf/otdfctl into 341-bug-when-c…
Browse files Browse the repository at this point in the history
…ommands-expected-to-output-json-should-not-print-using-profile-profile-name
  • Loading branch information
jrschumacher committed Aug 30, 2024
2 parents 9587b29 + 30b823a commit eef8dbc
Show file tree
Hide file tree
Showing 12 changed files with 353 additions and 47 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ jobs:
end-to-end:
name: e2e tests
runs-on: ubuntu-22.04
env:
BATS_LIB_PATH: /usr/lib
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Check out platform
Expand Down Expand Up @@ -98,10 +100,13 @@ jobs:

- name: build the CLI
run: go build .
- name: build the CLI in test mode
run: make build-test
- name: set up the config
run: cp otdfctl-example.yaml otdfctl.yaml
- name: Setup Bats and bats libs
uses: bats-core/[email protected]
- run: tests/encrypt-decrypt.bats
- run: tests/kas-grants.bats
- run: tests/profile.bats
- run: tests/kas-registry.bats
7 changes: 5 additions & 2 deletions .github/workflows/spellcheck.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ jobs:
- uses: actions/checkout@v3
- uses: matheus23/[email protected]
with:
files-to-check: '**/*.md'
files-to-exclude: 'CHANGELOG.md'
files-to-check: |
**/*.md
files-to-exclude: |
CHANGELOG.md
adr/**/*.md
words-to-ignore-file: './.github/spellcheck.ignore'
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ target/
.vscode/launch.json
otdfctl.yaml

# Ignore the tructl binary
# Ignore the binaries
otdfctl
otdfctl.*
otdfctl_testbuild
otdfctl_testbuild.*

# Misc
# Test artifacts
creds.json

# Hugo
Expand Down
38 changes: 34 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ GO_MOD_LINE = $(shell head -n 1 go.mod | cut -c 8-)
GO_MOD_NAME = $(word 1,$(subst /, ,$(GO_MOD_LINE)))
APP_CFG = $(GO_MOD_LINE)/pkg/config

GO_BUILD_FLAGS=-ldflags "-X $(APP_CFG).Version=${CURR_VERSION} -X $(APP_CFG).CommitSha=${COMMIT_SHA} -X $(APP_CFG).BuildTime=${BUILD_TIME}"
GO_BUILD_FLAGS=-ldflags " \
-X $(APP_CFG).Version=${CURR_VERSION} \
-X $(APP_CFG).CommitSha=${COMMIT_SHA} \
-X $(APP_CFG).BuildTime=${BUILD_TIME} \
"
GO_BUILD_PREFIX=$(TARGET_DIR)/$(BINARY_NAME)-${CURR_VERSION}

# If commit sha is not available try git
Expand All @@ -35,13 +39,24 @@ TARGET_DIR=target
# Output directory for the zipped artifacts
OUTPUT_DIR=output

# Build commands for each platform
PLATFORMS := darwin-amd64 darwin-arm64 linux-amd64 linux-arm linux-arm64 windows-amd64-.exe windows-arm-.exe windows-arm64-.exe
# Build commands for each platform (extra hyphen used in windows to avoid issues with the .exe extension)
PLATFORMS := \
darwin-amd64 \
darwin-arm64 \
linux-amd64 \
linux-arm \
linux-arm64 \
windows-amd64-.exe \
windows-arm-.exe \
windows-arm64-.exe

build: test clean $(addprefix build-,$(PLATFORMS)) zip-builds verify-checksums

build-%:
GOOS=$(word 1,$(subst -, ,$*)) GOARCH=$(word 2,$(subst -, ,$*)) go build $(GO_BUILD_FLAGS) -o $(GO_BUILD_PREFIX)-$(word 1,$(subst -, ,$*))-$(word 2,$(subst -, ,$*))$(word 3,$(subst -, ,$*))
GOOS=$(word 1,$(subst -, ,$*)) \
GOARCH=$(word 2,$(subst -, ,$*)) \
go build $(GO_BUILD_FLAGS) \
-o $(GO_BUILD_PREFIX)-$(word 1,$(subst -, ,$*))-$(word 2,$(subst -, ,$*))$(word 3,$(subst -, ,$*))

zip-builds:
./.github/scripts/zip-builds.sh $(BINARY_NAME)-$(CURR_VERSION) $(TARGET_DIR) $(OUTPUT_DIR)
Expand All @@ -59,6 +74,21 @@ run:
test:
go test -v ./...

.PHONY: build-test
build-test:
go build \
-ldflags "\
-X $(APP_CFG).TestMode=true \
-X $(APP_CFG).Version=${CURR_VERSION}-testbuild \
-X $(APP_CFG).CommitSha=${COMMIT_SHA} \
-X $(APP_CFG).BuildTime=${BUILD_TIME} \
" \
-o $(BINARY_NAME)_testbuild

.PHONY: test-bats
test-bats: build-test
bats ./tests

# Target for cleaning up the target directory
.PHONY: clean
clean:
Expand Down
49 changes: 22 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,30 +54,25 @@ CLI via the `man.Docs.GetDoc()` function.

## Testing

The [tests](./tests) directory contains e2e Bash Automated Test System (bats) tests for all of the cli functionality.

To install bats on MacOS:
```
$ brew install bats-core
```
Or with NPM on any OS:
```
# To install globally:
$ npm install -g bats
# To install into your project and save it as one of the "devDependencies" in
# your package.json:
$ npm install --save-dev bats
```

These tests require the platform to be running and provisioned with basic keycloak clients/users. Before running, clone https://github.com/opentdf/platform and follow [the quickstart](https://github.com/opentdf/platform?tab=readme-ov-file#quick-start) to spin it up.

Build the cli:
```
$ go build .
```

Run the bats with:
```
$ bats tests/*.bats
```
The CLI is equipped with a test mode that can be enabled by building the CLI with `config.TestMode = true`.
For convenience, the CLI can be built with `make build-test`.

**Test Mode features**:

- Use the in-memory keyring provider for user profiles
- Enable provisioning profiles for testing via `OTDFCTL_TEST_PROFILE` environment variable

### BATS

> [!NOTE]
> Bat Automated Test System (bats) is a TAP-compliant testing framework for Bash. It provides a simple way to verify that the UNIX programs you write behave as expected.
BATS is used to test the CLI from an end-to-end perspective. To run the tests you will need to ensure the following
prerequisites are met:

- bats is installed on your system
- MacOS: `brew install bats-core bats-support bats-assert`
- The platform is running and provisioned with basic keycloak clients/users
- See the [platform README](https://github.com/opentdf/platform) for instructions

To run the tests you can either run `make test-bats` or execute specific test suites with `bats tests/<test>.bats`.
44 changes: 44 additions & 0 deletions adr/0000-use-adr-dir-for-adr.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
status: accepted
date: 2024-08-29
decision: Use ADRs in the `adr` directory of the repo to document architectural decisions
author: '@jakedoublev'
deciders: ['@ryanulit', '@jrschumacher']
---

# Use a ADR storage format that make diffs easier to read

## Context and Problem Statement

We've been using Github Issues to document ADR decisions, but it's hard to read the diffs when changes are made. We need a better way to store and manage ADRs. ADRs sometimes get updated and it's hard to track the changes and decision using the edit history dropdown or the comments section.

## Decision Drivers

- **Low barrier of entry**: A primary goal of our ADR process is to ensure decisions are captured.
- **Ease of management**: Make it easy to manage the ADRs.
- **Ensure appropriate tracking and review**: Make it easy to track and review the changes in the ADRs.

## Considered Options

1. Use Github Issues
2. Use Github Discussions
3. Use a shared ADR repository
4. Use an `adr` directory in the repo

## Decision Outcome

It was decided to use an `adr` directory in the repo to store ADRs. This approach provides a low barrier of entry for developers to document decisions and ensures that the decisions are tracked and reviewed appropriately.

Additionally, this change does not impact other teams or repositories, and it is easy to manage and maintain. We can experiment with this decision and if it works promote it to other repositories.

### Consequences

- **Positive**:
- Low barrier of entry for developers to document decisions.
- Easy to manage and maintain.
- Ensures appropriate tracking and review of decisions via git history and code review.
- **Negative**:
- Requires developers to be aware of the ADR process and where to find the ADRs.
- May require additional tooling to manage and maintain the ADRs.
- May require additional training for developers to understand the ADR process and how to use it effectively.

5 changes: 3 additions & 2 deletions cmd/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"runtime"

"github.com/opentdf/otdfctl/pkg/cli"
"github.com/opentdf/otdfctl/pkg/config"
"github.com/opentdf/otdfctl/pkg/profiles"
"github.com/spf13/cobra"
)
Expand Down Expand Up @@ -160,8 +161,8 @@ var profileSetEndpointCmd = &cobra.Command{
}

func init() {
// Profiles are not supported on Linux
if runtime.GOOS == "linux" {
// Profiles are not supported on Linux (unless mocked in test mode)
if runtime.GOOS == "linux" && config.TestMode != "true" {
return
}

Expand Down
22 changes: 14 additions & 8 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ import (
"github.com/spf13/viper"
)

// AppName is the name of the application
// Note: use caution when renaming as it is used in various places within the CLI including for config file naming
// and in the profile store
var AppName = "otdfctl"

var Version = "0.0.0"
var BuildTime = "1970-01-01T00:00:00Z"
var CommitSha = "0000000"
var (
// AppName is the name of the application
// Note: use caution when renaming as it is used in various places within the CLI including for
// config file naming and in the profile store
AppName = "otdfctl"

Version = "0.0.0"
BuildTime = "1970-01-01T00:00:00Z"
CommitSha = "0000000"

// Test mode is used to determine if the application is running in test mode
// "true" = running in test mode
TestMode = ""
)

type Output struct {
Format string `yaml:"format" default:"styled"`
Expand Down
4 changes: 4 additions & 0 deletions pkg/profiles/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ func newStoreFactory(driver string) NewStoreInterface {
func New(opts ...profileConfigVariadicFunc) (*Profile, error) {
var err error

if testProfile != nil {
return testProfile, nil
}

config := profileConfig{
driver: PROFILE_DRIVER_DEFAULT,
}
Expand Down
2 changes: 0 additions & 2 deletions pkg/profiles/storeKeyring.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ import (
"github.com/zalando/go-keyring"
)

// TODO: update the store to use alternative storage methods besides keyring

type KeyringStore struct {
namespace string
key string
Expand Down
74 changes: 74 additions & 0 deletions pkg/profiles/test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package profiles

import (
"bytes"
"encoding/json"
"fmt"
"os"

"github.com/opentdf/otdfctl/pkg/config"
"github.com/zalando/go-keyring"
)

const testModeMsg = `
********************
RUNNING IN TEST MODE
test config: %s
********************
`

var (
testProfile *Profile
testCfg = os.Getenv("OTDFCTL_TEST_PROFILE")
)

type testConfig struct {
// global config is used to get the store in a bad state
GlobalConfig config.Config `json:"globalConfig,omitempty"`

// set the default profile
DefaultProfile string `json:"defaultProfile,omitempty"`

// profiles to add
Profiles []ProfileConfig `json:"profiles,omitempty"`
}

func init() {
// If running in test mode, use the mock keyring
if config.TestMode == "true" {
fmt.Printf(testModeMsg, testCfg)

keyring.MockInit()

// configure the keyring based on the test config
// unmarsal the test config
if testCfg != "" {
var err error
var cfg testConfig
if err := json.NewDecoder(bytes.NewReader([]byte(testCfg))).Decode(&cfg); err != nil {
panic(err)
}

testProfile, err = New()
if err != nil {
panic(err)
}

for _, p := range cfg.Profiles {
err := testProfile.AddProfile(p.Name, p.Endpoint, p.TlsNoVerify, cfg.DefaultProfile == p.Name)
if err != nil {
panic(err)
}
}

// set default
if cfg.DefaultProfile != "" {
if err := testProfile.SetDefaultProfile(cfg.DefaultProfile); err != nil {
panic(err)
}
}
}
}
}
Loading

0 comments on commit eef8dbc

Please sign in to comment.