Skip to content

Commit

Permalink
init commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mina1460 committed Jan 16, 2024
1 parent 77cbc14 commit 3863b4f
Show file tree
Hide file tree
Showing 6 changed files with 185 additions and 34 deletions.
17 changes: 13 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/canonical/jimm

go 1.21.3
go 1.21.4

toolchain go1.21.6

require (
github.com/canonical/candid v1.12.2
Expand Down Expand Up @@ -111,7 +113,7 @@ require (
github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/creack/pty v1.1.15 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
Expand Down Expand Up @@ -183,6 +185,9 @@ require (
github.com/jackc/pgproto3/v2 v2.3.1 // indirect
github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect
github.com/jackc/pgtype v1.12.0 // indirect
github.com/jackc/pgx v3.6.2+incompatible
github.com/jackc/pgx/v5 v5.5.1 // indirect
github.com/jackc/puddle/v2 v2.2.1 // indirect
github.com/jhump/protoreflect v1.8.2 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
Expand Down Expand Up @@ -290,6 +295,9 @@ require (
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.37.0 // indirect
github.com/prometheus/procfs v0.11.0 // indirect
github.com/riverqueue/river v0.0.16 // indirect
github.com/riverqueue/river/riverdriver v0.0.15 // indirect
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.0.16 // indirect
github.com/rivo/tview v0.0.0-20220610163003-691f46d6f500 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
Expand All @@ -304,7 +312,7 @@ require (
github.com/sony/gobreaker v0.5.0 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/cobra v1.8.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.16.0 // indirect
Expand Down Expand Up @@ -339,7 +347,8 @@ require (
go.uber.org/mock v0.2.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/oauth2 v0.13.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
Expand Down
16 changes: 16 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:ma
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
Expand Down Expand Up @@ -992,6 +993,8 @@ github.com/jackc/pgtype v1.5.0/go.mod h1:JCULISAZBFGrHaOXIIFiyfzW5VY0GRitRr8NeJs
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.12.0 h1:Dlq8Qvcch7kiehm8wPGIW0W3KsCCHJnRacKW0UM8n5w=
github.com/jackc/pgtype v1.12.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx v3.6.2+incompatible h1:2zP5OD7kiyR3xzRYMhOcXVvkDZsImVXfj+yIyTQf3/o=
github.com/jackc/pgx v3.6.2+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
Expand All @@ -1002,13 +1005,18 @@ github.com/jackc/pgx/v4 v4.9.0/go.mod h1:MNGWmViCgqbZck9ujOOBN63gK9XVGILXWCvKLGK
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.17.2 h1:0Ut0rpeKwvIVbMQ1KbMBU4h6wxehBI535LK6Flheh8E=
github.com/jackc/pgx/v4 v4.17.2/go.mod h1:lcxIZN44yMIrWI78a5CpucdD14hX0SBDbNRvjDBItsw=
github.com/jackc/pgx/v5 v5.5.1 h1:5I9etrGkLrN+2XPCsi6XLlV5DITbSL/xBZdmAxFcXPI=
github.com/jackc/pgx/v5 v5.5.1/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.2/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.3.0 h1:eHK/5clGOatcjX3oWGBO/MpxpbHzSwud5EWTSCI+MX0=
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
github.com/jarcoal/httpmock v1.3.0 h1:2RJ8GP0IIaWwcC9Fp2BmVi8Kog3v2Hn7VXM3fTd+nuc=
github.com/jarcoal/httpmock v1.3.0/go.mod h1:3yb8rc4BI7TCBhFY8ng0gjuLKJNquuDNiPaZjnENuYg=
Expand Down Expand Up @@ -1648,6 +1656,12 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
github.com/pseudomuto/protoc-gen-doc v1.4.1/go.mod h1:exDTOVwqpp30eV/EDPFLZy3Pwr2sn6hBC1WIYH/UbIg=
github.com/pseudomuto/protokit v0.2.0/go.mod h1:2PdH30hxVHsup8KpBTOXTBeMVhJZVio3Q8ViKSAXT0Q=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/riverqueue/river v0.0.16 h1:rqbWGyiGMLD2OkzzPHhyR1Oh0l80ZPavXLH8+cerTIs=
github.com/riverqueue/river v0.0.16/go.mod h1:1zLtldMgoTfDj4ouXFNGsF4bzqb9Y2Ds3WuDFanugJ0=
github.com/riverqueue/river/riverdriver v0.0.15 h1:BB26eGIB+xK4dpQ9w5WUxWHbDZbk0E+tmajGRYvI/hM=
github.com/riverqueue/river/riverdriver v0.0.15/go.mod h1:vtgL7tRTSB6rzeVEDppehd/rPx3Is+WBYb17Zj0+KsE=
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.0.16 h1:kUr40A6sVrw3blSxQQo3T0LgiO6qRbSzK2u4Vjml6Ww=
github.com/riverqueue/river/riverdriver/riverpgxv5 v0.0.16/go.mod h1:w365SHh6QB96Yea/SsGBdUAhGGvlWhU9+v2AVwJSjBc=
github.com/rivo/tview v0.0.0-20220610163003-691f46d6f500 h1:KvoRB2TMfMqK2NF2mIvZprDT/Ofvsa4RphWLoCmUDag=
github.com/rivo/tview v0.0.0-20220610163003-691f46d6f500/go.mod h1:WIfMkQNY+oq/mWwtsjOYHIZBuwthioY2srOmljJkTnk=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
Expand Down Expand Up @@ -1744,6 +1758,7 @@ github.com/spf13/cobra v1.1.3/go.mod h1:pGADOWyqRD/YMrPZigI/zbliZ2wVD/23d+is3pSW
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
Expand Down Expand Up @@ -2046,6 +2061,7 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20150829230318-ea47fc708ee3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
Expand Down
2 changes: 2 additions & 0 deletions internal/jimm/jimm.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ type JIMM struct {
JWKService *jimmjwx.JWKSService

JWTService *jimmjwx.JWTService

River *River
}

// ResourceTag returns JIMM's controller tag stating its UUID.
Expand Down
55 changes: 25 additions & 30 deletions internal/jimm/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/juju/names/v4"
"github.com/juju/zaputil"
"github.com/juju/zaputil/zapctx"
"github.com/riverqueue/river"
"go.uber.org/zap"

"github.com/canonical/jimm/internal/constants"
Expand Down Expand Up @@ -483,17 +484,6 @@ func (b *modelBuilder) CreateControllerModel() *modelBuilder {
return b
}

// Grant JIMM admin access to the model. Note that if this fails,
// the local database entry will be deleted but the model
// will remain on the controller and will trigger the "already exists
// in the backend controller" message above when the user
// attempts to create a model with the same name again.
if err := api.GrantJIMMModelAdmin(b.ctx, names.NewModelTag(info.UUID)); err != nil {
zapctx.Error(b.ctx, "leaked model", zap.String("model", info.UUID), zaputil.Error(err))
b.err = errors.E(err)
return b
}

b.modelInfo = &info
return b
}
Expand Down Expand Up @@ -625,27 +615,32 @@ func (j *JIMM) AddModel(ctx context.Context, user *openfga.User, args *ModelCrea
}

mi := builder.JujuModelInfo()

if err := j.OpenFGAClient.AddControllerModel(
ctx,
builder.controller.ResourceTag(),
builder.model.ResourceTag(),
); err != nil {
zapctx.Error(
ctx,
"failed to add controller-model relation",
zap.String("controller", builder.controller.UUID),
zap.String("model", builder.model.UUID.String),
)
}
err = openfga.NewUser(owner, j.OpenFGAClient).SetModelAccess(ctx, names.NewModelTag(mi.UUID), ofganames.AdministratorRelation)
openfga_river_job_args := OpenFGAArgs{client: *j.OpenFGAClient, controller: builder.controller, model: builder.model, owner: builder.owner, modelInfo: mi}
_, err = j.River.Client.Insert(ctx, openfga_river_job_args, &river.InsertOpts{MaxAttempts: 10})
if err != nil {
zapctx.Error(
zapctx.Error(ctx, "Failed to insert river job!", zaputil.Error(err))
// trying without river just in case.
if err := j.OpenFGAClient.AddControllerModel(
ctx,
"failed to add administrator relation",
zap.String("user", owner.Tag().String()),
zap.String("model", builder.model.UUID.String),
)
builder.controller.ResourceTag(),
builder.model.ResourceTag(),
); err != nil {
zapctx.Error(
ctx,
"failed to add controller-model relation",
zap.String("controller", builder.controller.UUID),
zap.String("model", builder.model.UUID.String),
)
}
err = openfga.NewUser(owner, j.OpenFGAClient).SetModelAccess(ctx, names.NewModelTag(mi.UUID), ofganames.AdministratorRelation)
if err != nil {
zapctx.Error(
ctx,
"failed to add administrator relation",
zap.String("user", owner.Tag().String()),
zap.String("model", builder.model.UUID.String),
)
}
}

return mi, nil
Expand Down
127 changes: 127 additions & 0 deletions internal/jimm/river.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2024 Canonical Ltd.

package jimm

import (
"context"
"log/slog"

"github.com/canonical/jimm/internal/dbmodel"
"github.com/canonical/jimm/internal/openfga"
ofganames "github.com/canonical/jimm/internal/openfga/names"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/pgxpool"
jujuparams "github.com/juju/juju/rpc/params"
"github.com/juju/names/v4"
"github.com/juju/zaputil/zapctx"
"github.com/riverqueue/river"
"github.com/riverqueue/river/riverdriver/riverpgxv5"
"github.com/riverqueue/river/rivermigrate"
"go.uber.org/zap"
)

type OpenFGAArgs struct {
client openfga.OFGAClient
controller *dbmodel.Controller
model *dbmodel.Model
owner *dbmodel.User
modelInfo *jujuparams.ModelInfo
}

func (OpenFGAArgs) Kind() string { return "OpenFGA" }

type OpenFGAWorker struct {
river.WorkerDefaults[OpenFGAArgs]
}

func (w *OpenFGAWorker) Work(ctx context.Context, job *river.Job[OpenFGAArgs]) error {
model := job.Args.model
controller := job.Args.controller
owner := job.Args.owner
modelInfo := job.Args.modelInfo
if err := job.Args.client.AddControllerModel(
ctx,
controller.ResourceTag(),
model.ResourceTag(),
); err != nil {
zapctx.Error(
ctx,
"failed to add controller-model relation",
zap.String("controller", controller.UUID),
zap.String("model", model.UUID.String),
)
return err
}
err := openfga.NewUser(owner, &job.Args.client).SetModelAccess(ctx, names.NewModelTag(modelInfo.UUID), ofganames.AdministratorRelation)
if err != nil {
zapctx.Error(
ctx,
"failed to add administrator relation",
zap.String("user", owner.Tag().String()),
zap.String("model", model.UUID.String),
)
return err
}
return nil
}

func RegisterJimmWorkers(ctx context.Context) *river.Workers {
workers := river.NewWorkers()
if err := river.AddWorkerSafely(workers, &OpenFGAWorker{}); err != nil {
zapctx.Error(ctx, "Failed to register OpenFGA client", zap.Error(err))
}
return workers
}

type River struct {
Client *river.Client[pgx.Tx]
}

func doMigration(ctx context.Context, dburl string) {
var dbPool *pgxpool.Pool
migrator := rivermigrate.New(riverpgxv5.New(dbPool), nil)
dbPool, err := pgxpool.New(ctx, dburl)
if err != nil {
panic(err)
}
defer dbPool.Close()

tx, err := dbPool.Begin(ctx)
if err != nil {
panic(err)
}
defer tx.Rollback(ctx)
_, err = migrator.MigrateTx(ctx, tx, rivermigrate.DirectionUp, nil)
if err != nil {
zapctx.Error(ctx, "Failed to apply DB migration", zap.Error(err))
}
}

func NewRiver(config *river.Config, db_url string, ctx context.Context) *River {
doMigration(ctx, db_url)
if config == nil {
config = &river.Config{
RetryPolicy: &river.DefaultClientRetryPolicy{},
Queues: map[string]river.QueueConfig{
river.QueueDefault: {MaxWorkers: 100},
},
Logger: slog.Default(),
Workers: RegisterJimmWorkers(ctx),
}
}
dbPool, err := pgxpool.New(ctx, db_url)
if err != nil {
zapctx.Error(ctx, "Failed to create db pool", zap.Error(err))
}
riverClient, err := river.NewClient(riverpgxv5.New(dbPool), config)
if err != nil {
zapctx.Error(ctx, "Failed to create river client", zap.Error(err))
}
if err := riverClient.Start(ctx); err != nil {
zapctx.Error(ctx, "FailedFailed to start river client", zap.Error(err))
}
r := River{
Client: riverClient,
}
return &r
}
2 changes: 2 additions & 0 deletions service.go
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ func NewService(ctx context.Context, p Params) (*Service, error) {
return nil, errors.E(op, err)
}

s.jimm.River = jimm.NewRiver(nil, p.DSN, ctx)

if err := s.setupCredentialStore(ctx, p); err != nil {
return nil, errors.E(op, err)
}
Expand Down

0 comments on commit 3863b4f

Please sign in to comment.