Skip to content
This repository was archived by the owner on Jan 30, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ productctl
!internal/cmd/productctl
*.env
*completion*
# dir-local configuration
.productctl/

# Test binary, build with `go test -c`
*.test
Expand All @@ -30,4 +32,4 @@ bin
.DS_Store

# Vagrant
.vagrant
.vagrant
40 changes: 27 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,27 @@ Certification Components and Product Listings from your workstation.
> - This tool is not supported by Red Hat Support.
> - Every API used here is subject to change.

## Configuration

Create a configuration file at any of these locations (listed in order of precedence):

- $PWD/.productctl/config.yaml
- $XDG_CONFIG_DIR/.productctl/config.yaml
- $HOME/.productctl/config.yaml

Example contents:

```yaml
# env: PRODUCTCTL_API_TOKEN
api-token: your-api-token

# env: PRODUCTCTL_LOG_LEVEL
log-level: "info"
```

Alternatively, you can set the environment variables mentioned in-line.

## Usage

```
Manage your Product Listing
Expand Down Expand Up @@ -46,14 +67,7 @@ Use "productctl product [command] --help" for more information about a command.

## High Level Workflow

0) (Prereq) Make sure your environment has the necessary variables

```bash
export CONNECT_API_TOKEN=yourtoken
export CONNECT_ORG_ID=000000000
```

1) Scaffold your new Product Listing (or fetch an existing one)
1. Scaffold your new Product Listing (or fetch an existing one)

```bash
productctl product create [--from-discovery-json /path/to/discovery.json] my.product.yaml
Expand All @@ -65,17 +79,17 @@ Or fetch an existing listing:
productctl product fetch 000111222333 > my.product.yaml
```

2) Make alterations to your Product Listing, add/remove components, etc.
2. Make alterations to your Product Listing, add/remove components, etc.

3) Apply your Product Listing
3. Apply your Product Listing

```bash
productctl product apply my.product.yaml
```

4) Repeat until all metadata is configured to your liking.

4. Repeat until all metadata is configured to your liking.

## Getting Started

See our [Getting Started](docs/GETTING_STARTED.md) guide.
See our [Getting Started](docs/GETTING_STARTED.md) guide.

15 changes: 3 additions & 12 deletions docs/PREREQS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,11 @@
You will need an established Red Hat Partner Connect account. This tool will not
create this for you.

You'll need to set two environment variables to use `productctl`.

| Env Var | Description |
|-|-|
|`CONNECT_ORG_ID` |The organization you're working against. Helps in filtering queries.|
|`CONNECT_API_TOKEN`| Your API token. Used to scope requests just to your project.|
You will need a Connect API Token to use this tooling, set to either the
`PRODUCTCTL_API_TOKEN` environment variable, or in your configuration file at
the `api-token` key.

### Getting an API token:

Log into Red Hat Partner Connect and access this URL:
https://connect.redhat.com/account/api-keys

### Getting your ORG ID

Log into Red Hat Partner Connect and access this URL:
https://connect.redhat.com/account/company-profile. Your ORG ID should be listed
at the top of this UI.
13 changes: 12 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,34 @@ require (
github.com/onsi/gomega v1.38.0
github.com/opdev/discover-workload v0.0.0-20250613205600-4f6ee215f625
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.6
github.com/spf13/viper v1.20.1
sigs.k8s.io/yaml v1.6.0
)

require (
github.com/bahlo/generic-list-go v0.2.0 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.8.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/spf13/pflag v1.0.6 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/sagikazarmark/locafero v0.7.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.12.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/vektah/gqlparser/v2 v2.5.22 // indirect
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
go.yaml.in/yaml/v2 v2.4.2 // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sys v0.33.0 // indirect
Expand Down
38 changes: 34 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@ github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xW
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
Expand All @@ -24,8 +32,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
Expand All @@ -36,25 +44,47 @@ github.com/onsi/gomega v1.38.0 h1:c/WX+w8SLAinvuKKQFh77WEucCnPk4j2OTUr7lt7BeY=
github.com/onsi/gomega v1.38.0/go.mod h1:OcXcwId0b9QsE7Y49u+BTrL4IdKOBOKnD6VQNTJEB6o=
github.com/opdev/discover-workload v0.0.0-20250613205600-4f6ee215f625 h1:kIvS4Q0WQJOg/TXGr7Web+krA9SZsINe8CUZ27zoF98=
github.com/opdev/discover-workload v0.0.0-20250613205600-4f6ee215f625/go.mod h1:Evlxr5q2psdSnx1Fdf0WJouLvcXlGyETN5hdaDLh8Fo=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sagikazarmark/locafero v0.7.0 h1:5MqpDsTGNDhY8sGp0Aowyf0qKsPrhewaLSsFaodPcyo=
github.com/sagikazarmark/locafero v0.7.0/go.mod h1:2za3Cg5rMaTMoG/2Ulr9AwtFaIppKXTRYnozin4aB5k=
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs=
github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/vektah/gqlparser/v2 v2.5.22 h1:yaaeJ0fu+nv1vUMW0Hl+aS1eiv1vMfapBNjpffAda1I=
github.com/vektah/gqlparser/v2 v2.5.22/go.mod h1:xMl+ta8a5M1Yo1A1Iwt/k7gSpscwSnHZdw7tfhEGfTM=
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
go.yaml.in/yaml/v3 v3.0.3 h1:bXOww4E/J3f66rav3pX3m8w6jDE4knZjGOw8b5Y6iNE=
Expand All @@ -70,8 +100,8 @@ golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
Expand Down
36 changes: 1 addition & 35 deletions internal/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,14 @@ package cli
import (
"context"
"errors"
"fmt"
"io"
"log/slog"
"os"
"strconv"

"github.com/opdev/productctl/internal/catalogapi"
"github.com/opdev/productctl/internal/logger"
)

var (
ErrEnvVarMissing = errors.New("required environment variable is missing")
ErrEnvVarInvalidFormat = errors.New("required environment variable is malformed")
ErrAPIEndpointUnknown = errors.New("unknown api endpoint")
)

var (
EnvAPIToken = "CONNECT_API_TOKEN"
EnvOrgID = "CONNECT_ORG_ID"
)

// EnsureEnv looks for the minimum required environment variables for the CLI to function
func EnsureEnv() (int, string, error) {
token := os.Getenv(EnvAPIToken)
orgIDstr := os.Getenv(EnvOrgID)

if token == "" {
return 0, "", fmt.Errorf("%w: CONNECT_API_TOKEN must be set", ErrEnvVarMissing)
}

if orgIDstr == "" {
return 0, "", fmt.Errorf("%w: CONNECT_ORG_ID must be set", ErrEnvVarMissing)
}

var orgID int
var err error
if orgID, err = strconv.Atoi(orgIDstr); err != nil {
return 0, "", fmt.Errorf("%w: OrgID did not convert nicely to an integer which is unexpected", ErrEnvVarInvalidFormat)
}

return orgID, token, nil
}
var ErrAPIEndpointUnknown = errors.New("unknown api endpoint")

// ConfigureLogger serves as a convenience function for configuring the CLI logger,
// populating a context with it, and returning it to the user.
Expand Down
73 changes: 0 additions & 73 deletions internal/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ package cli_test

import (
"bytes"
"fmt"
"io"
"os"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
Expand All @@ -15,77 +13,6 @@ import (
)

var _ = Describe("CLI", func() {
When("ensuring the environment", func() {
var (
expectedToken string
expectedOrgID string
)

AfterEach(func() {
os.Setenv(cli.EnvAPIToken, "")
os.Setenv(cli.EnvOrgID, "")
})

When("the caller sets the expected environment variables", func() {
BeforeEach(func() {
expectedToken = "foo"
expectedOrgID = "1234"
os.Setenv(cli.EnvAPIToken, expectedToken)
os.Setenv(cli.EnvOrgID, expectedOrgID)
})
It("should return the orgID as an integer equivalent of the string input", func() {
resolvedOrgID, _, err := cli.EnsureEnv()
Expect(err).ToNot(HaveOccurred())
Expect(expectedOrgID).To(BeEquivalentTo(fmt.Sprintf("%d", resolvedOrgID)))
})
It("should return the token value from the environment", func() {
_, resolvedToken, err := cli.EnsureEnv()
Expect(err).ToNot(HaveOccurred())
Expect(resolvedToken).To(Equal(expectedToken))
})

When("the orgID format is not a valid integer", func() {
// The catalog API expects OrgID to be an integer type, but
// environment variables are always strings, so we do the
// conversion and throw an error if it doesn't succeed.
//
// This also implies that OrgIDs can't lead with 0 because
// integer conversion would drop that. Therefore, we assume
// OrgIDs can never have a leading 0.
BeforeEach(func() {
expectedOrgID = "abcd"
os.Setenv(cli.EnvOrgID, expectedOrgID)
})
It("should throw an error indicating the value is malformed", func() {
_, _, err := cli.EnsureEnv()
Expect(err).To(MatchError(cli.ErrEnvVarInvalidFormat))
})
})
})

When("the caller is missing the token", func() {
BeforeEach(func() {
os.Setenv(cli.EnvAPIToken, "")
os.Setenv(cli.EnvOrgID, "1234")
})
It("should throw the expected error when the token is missing", func() {
_, _, err := cli.EnsureEnv()
Expect(err).To(MatchError(cli.ErrEnvVarMissing))
})
})

When("the caller is missing the orgID", func() {
BeforeEach(func() {
os.Setenv(cli.EnvAPIToken, "foo")
os.Setenv(cli.EnvOrgID, "")
})
It("should throw the expected error when the org ID is missing", func() {
_, _, err := cli.EnsureEnv()
Expect(err).To(MatchError(cli.ErrEnvVarMissing))
})
})
})

When("configuring the logger", func() {
var (
loglevel string
Expand Down
Loading