Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RHCLOUD-35503 updates defaults and adds config pkg #176

Merged
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
6 changes: 3 additions & 3 deletions .inventory-api.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
server:
public_url: http://localhost:8081
public_url: http://localhost:8000
http:
address: localhost:8081
address: localhost:8000
grpc:
address: localhost:9081
address: localhost:9000
authn:
allow-unauthenticated: true
authz:
Expand Down
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,5 +188,33 @@ authz:
sa-client-secret: "<secret>"
sso-token-endpoint: "http://localhost:8084/realms/redhat-external/protocol/openid-connect/token"
```
## Running in Ephemeral Cluster with Relations API using Bonfire
Deploy Relations API first with Bonfire following the steps available [HERE](https://cuddly-tribble-gq7r66v.pages.github.io/kessel/ephemeral/)
Once its running, deploy Inventory using Bonfire:
`bonfire deploy kessel -C inventory-api --no-get-dependencies`

If you wish to test changes you've made that are unmerged, you can deploy them to ephemeral using a local config file
Note: this requires building the image first and pushing to your local quay (see make docker-build-push)

```yaml
# example local config under $HOME/.config/bonfire/config
apps:
- name: kessel
components:
- name: inventory-api
host: local
repo: /path/to/inventory-api-repo
path: deploy/kessel-inventory.yaml
parameters:
INVENTORY_IMAGE: quay.io/your-repo/image-name
IMAGE_TAG: your-image-tag # latest is not recommended due to pull policy
```

Then run `bonfire deploy kessel -c $HOME/.config/bonfire/config.yaml --local-config-method override --no-get-dependencies`

## Debugging Inventory API using Vscode
Follow the [DEBUG](./DEBUG.md) guide
6 changes: 3 additions & 3 deletions cmd/.inventory-api.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
server:
public_url: http://localhost:8081
public_url: http://localhost:8000
http:
address: localhost:8081
address: localhost:8000
grpc:
address: localhost:9081
address: localhost:9000
authn:
allow-unauthenticated: true
authz:
Expand Down
46 changes: 14 additions & 32 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,19 @@ package cmd

import (
"fmt"
"github.com/project-kessel/inventory-api/internal/config"
clowder "github.com/redhatinsights/app-common-go/pkg/api/v1"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"os"
"path/filepath"
"strings"
"strconv"

"github.com/spf13/cobra"
"github.com/spf13/viper"

"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/middleware/tracing"

"github.com/project-kessel/inventory-api/cmd/migrate"
"github.com/project-kessel/inventory-api/cmd/serve"

"github.com/project-kessel/inventory-api/internal/authn"
"github.com/project-kessel/inventory-api/internal/authz"
"github.com/project-kessel/inventory-api/internal/eventing"
"github.com/project-kessel/inventory-api/internal/server"
"github.com/project-kessel/inventory-api/internal/storage"
clowder "github.com/redhatinsights/app-common-go/pkg/api/v1"
)

// go build -ldflags "-X cmd.Version=x.y.z"
Expand All @@ -40,19 +33,7 @@ var (
Short: "A simple common inventory system",
}

options = struct {
Authn *authn.Options `mapstructure:"authn"`
Authz *authz.Options `mapstructure:"authz"`
Storage *storage.Options `mapstructure:"storage"`
Eventing *eventing.Options `mapstructure:"eventing"`
Server *server.Options `mapstructure:"server"`
}{
authn.NewOptions(),
authz.NewOptions(),
storage.NewOptions(),
eventing.NewOptions(),
server.NewOptions(),
}
options = config.NewOptionsConfig()
)

// Execute is called by main.main(). It only needs to happen once to the rootCmd.
Expand Down Expand Up @@ -85,20 +66,21 @@ func init() {
panic(err)
}

if clowder.IsClowderEnabled() {
options.Storage.Postgres.Host = clowder.LoadedConfig.Database.Hostname
options.Storage.Postgres.Port = strconv.Itoa(clowder.LoadedConfig.Database.Port)
options.Storage.Postgres.User = clowder.LoadedConfig.Database.Username
options.Storage.Postgres.Password = clowder.LoadedConfig.Database.Password
options.Storage.Postgres.DbName = clowder.LoadedConfig.Database.Name
}

// TODO: Find a cleaner approach than explicitly calling initConfig
// Here we are calling the initConfig to ensure that the log level can be pulled from the inventory configuration file
initConfig()
logLevel := getLogLevel()
logger, baseLogger = initLogger(logLevel)

if clowder.IsClowderEnabled() {
options.InjectClowdAppConfig()
}

// for troubleshoot, when set to debug, configuration info is logged in more detail to stdout
if logLevel == "debug" {
config.LogConfigurationInfo(options)
}

migrateCmd := migrate.NewCommand(options.Storage, baseLogger)
rootCmd.AddCommand(migrateCmd)
err = viper.BindPFlags(migrateCmd.Flags())
Expand Down
20 changes: 5 additions & 15 deletions deploy/kessel-inventory.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,15 @@ objects:
name: inventory-api-config
data:
inventory-api-config.yaml: |
server:
http:
address: 0.0.0.0:8000
grpc:
address: 0.0.0.0:9000
authn:
psk:
pre-shared-key-file: /psks/psks.yaml
authz:
impl: kessel
kessel:
insecure-client: true
url: kessel-relations-api:9000
enable_oidc_auth: false
eventing:
eventer: stdout
kafka:
storage:
database: postgres
sqlite3:
dsn: inventory.db
enable-oidc-auth: false
log:
level: "info"
- apiVersion: v1
kind: ConfigMap
Expand All @@ -51,6 +39,8 @@ objects:
envName: ${ENV_NAME}
database:
name: kessel-inventory
optionalDependencies:
- kessel-relations
deployments:
- name: api
replicas: 1
Expand Down
5 changes: 4 additions & 1 deletion internal/authz/kessel/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ type Options struct {
}

func NewOptions() *Options {
return &Options{}
return &Options{
Insecure: false,
EnableOidcAuth: true,
}
}

func (o *Options) AddFlags(fs *pflag.FlagSet, prefix string) {
Expand Down
5 changes: 3 additions & 2 deletions internal/authz/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ type Options struct {
}

const (
AllowAll = "allow-all"
Kessel = "kessel"
AllowAll = "allow-all"
Kessel = "kessel"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here Kessel Refers to relations-api

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for adding the RelationsAPI = "kessel-relations" const is just so that i can reference that specific value HERE instead of hardcording "kessel-relations" in that method as this is the expected name of the relations ClowdApp that shows up in appconfig. This way if it ever changes, we just change the const

Similar to how the authz.impl config has a Kessel const which i use to set the impl value to 'kessel' in

o.Authz.Authz = authz.Kessel

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest changing the Kessel to RelationsAPI. authz.Kessel and RelationsAPI both are referring to "kessel-relations"

RelationsAPI = "kessel-relations"
)

func NewOptions() *Options {
Expand Down
94 changes: 94 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package config

import (
"fmt"
"github.com/go-kratos/kratos/v2/log"
"github.com/project-kessel/inventory-api/internal/authn"
"github.com/project-kessel/inventory-api/internal/authz"
"github.com/project-kessel/inventory-api/internal/eventing"
"github.com/project-kessel/inventory-api/internal/server"
"github.com/project-kessel/inventory-api/internal/storage"
clowder "github.com/redhatinsights/app-common-go/pkg/api/v1"
"strconv"
)

// OptionsConfig contains the settings for each configuration option
type OptionsConfig struct {
Authn *authn.Options
Authz *authz.Options
Storage *storage.Options
Eventing *eventing.Options
Server *server.Options
}

// NewOptionsConfig returns a new OptionsConfig with default options set
func NewOptionsConfig() *OptionsConfig {
return &OptionsConfig{
authn.NewOptions(),
authz.NewOptions(),
storage.NewOptions(),
eventing.NewOptions(),
server.NewOptions(),
}
}

// LogConfigurationInfo outputs connection details to logs when in debug for testing (no secret data is output)
func LogConfigurationInfo(options *OptionsConfig) {
log.Debugf("Server Configuration: Public URL: %s, HTTP Listener: %s, GRPC Listener: %s",
options.Server.PublicUrl,
options.Server.HttpOptions.Addr,
options.Server.GrpcOptions.Addr)

if options.Authn.Oidc.AuthorizationServerURL != "" {
log.Debugf("Authn Configuration: URL: %s, ClientID: %s",
options.Authn.Oidc.AuthorizationServerURL,
options.Authn.Oidc.ClientId,
)
}

if options.Storage.Database == storage.Postgres {
log.Debugf("Storage Configuration: Host: %s, DB: %s, Port: %s",
options.Storage.Postgres.Host,
options.Storage.Postgres.DbName,
options.Storage.Postgres.Port,
)
}

if options.Authz.Authz == authz.Kessel {
log.Debugf("Authz Configuration: URL: %s, Insecure?: %t, OIDC?: %t",
options.Authz.Kessel.URL,
options.Authz.Kessel.Insecure,
options.Authz.Kessel.EnableOidcAuth,
)
}
}

// InjectClowdAppConfig updates service options based on values in the ClowdApp AppConfig
func (o *OptionsConfig) InjectClowdAppConfig() {
// check for authz config
for _, endpoint := range clowder.LoadedConfig.Endpoints {
if endpoint.App == authz.RelationsAPI {
o.ConfigureAuthz(endpoint)
}
}
// check for db config
if clowder.LoadedConfig.Database != nil {
o.ConfigureStorage(clowder.LoadedConfig.Database)
}
}

// ConfigureAuthz updates Authz settings based on ClowdApp AppConfig
func (o *OptionsConfig) ConfigureAuthz(endpoint clowder.DependencyEndpoint) {
o.Authz.Authz = authz.Kessel
o.Authz.Kessel.URL = fmt.Sprintf("%s:%d", endpoint.Hostname, 9000)
}

// ConfigureStorage updates Storage settings based on ClowdApp AppConfig
func (o *OptionsConfig) ConfigureStorage(database *clowder.DatabaseConfig) {
o.Storage.Database = storage.Postgres
o.Storage.Postgres.Host = database.Hostname
o.Storage.Postgres.Port = strconv.Itoa(database.Port)
o.Storage.Postgres.User = database.Username
o.Storage.Postgres.Password = database.Password
o.Storage.Postgres.DbName = database.Name
}
69 changes: 69 additions & 0 deletions internal/config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package config

import (
clowder "github.com/redhatinsights/app-common-go/pkg/api/v1"
"github.com/stretchr/testify/assert"
"testing"
)

func TestConfigureStorage(t *testing.T) {
tests := []struct {
name string
appconfig *clowder.AppConfig
options *OptionsConfig
}{
{
name: "ensures DB info is set",
appconfig: &clowder.AppConfig{
Database: &clowder.DatabaseConfig{
Hostname: "postgres",
Name: "postgres",
Port: 5432,
Username: "db-user",
Password: "db-password",
},
},
options: NewOptionsConfig(),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
test.options.ConfigureStorage(test.appconfig.Database)
assert.Equal(t, "postgres", test.options.Storage.Database)
assert.Equal(t, "postgres", test.options.Storage.Postgres.Host)
assert.Equal(t, "postgres", test.options.Storage.Postgres.DbName)
assert.Equal(t, "5432", test.options.Storage.Postgres.Port)
assert.Equal(t, "db-user", test.options.Storage.Postgres.User)
assert.Equal(t, "db-password", test.options.Storage.Postgres.Password)
})
}
}

func TestConfigureAuthz(t *testing.T) {
tests := []struct {
name string
appconfig *clowder.AppConfig
options *OptionsConfig
}{
{
name: "ensures Authz info is set",
appconfig: &clowder.AppConfig{
Endpoints: []clowder.DependencyEndpoint{
clowder.DependencyEndpoint{
Hostname: "kessel-relations",
},
},
},
options: NewOptionsConfig(),
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
test.options.ConfigureAuthz(test.appconfig.Endpoints[0])
assert.Equal(t, "kessel", test.options.Authz.Authz)
assert.Equal(t, "kessel-relations:9000", test.options.Authz.Kessel.URL)
})
}
}
2 changes: 1 addition & 1 deletion internal/server/grpc/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Options struct {

func NewOptions() *Options {
return &Options{
Addr: "localhost:9080",
Addr: "0.0.0.0:9000",
Timeout: 300,
CertOpt: 3, // https://pkg.go.dev/crypto/tls#ClientAuthType
}
Expand Down
2 changes: 1 addition & 1 deletion internal/server/http/http_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestNewOptions(t *testing.T) {
opts := NewOptions()

expectedOpts := &Options{
Addr: "localhost:8080",
Addr: "0.0.0.0:8000",
Timeout: 300,
CertOpt: 3,
}
Expand Down
2 changes: 1 addition & 1 deletion internal/server/http/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type Options struct {

func NewOptions() *Options {
return &Options{
Addr: "localhost:8080",
Addr: "0.0.0.0:8000",
Timeout: 300,
CertOpt: 3, // https://pkg.go.dev/crypto/tls#ClientAuthType
}
Expand Down
Loading
Loading