diff --git a/cmd/jimmctl/cmd/purge_logs_test.go b/cmd/jimmctl/cmd/purge_logs_test.go index ac2676c9c..5283f5be4 100644 --- a/cmd/jimmctl/cmd/purge_logs_test.go +++ b/cmd/jimmctl/cmd/purge_logs_test.go @@ -74,7 +74,7 @@ func (s *purgeLogsSuite) TestPurgeLogsFromDb(c *gc.C) { IdentityTag: names.NewUserTag("alice@canonical.com").String(), } - err := s.JIMM.Database.Migrate(context.Background(), false) + err := s.JIMM.Database.Migrate(context.Background()) c.Assert(err, gc.IsNil) err = s.JIMM.Database.AddAuditLogEntry(ctx, &ale) c.Assert(err, gc.IsNil) diff --git a/docker-compose.yaml b/docker-compose.yaml index 9a43dbf46..3796ec64c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -101,6 +101,7 @@ services: OPENFGA_AUTHN_PRESHARED_KEYS: "jimm" OPENFGA_DATASTORE_ENGINE: "postgres" OPENFGA_DATASTORE_URI: "postgresql://jimm:jimm@db/jimm?sslmode=disable" + OPENFGA_LOG_LEVEL: "warn" volumes: - ./openfga/authorisation_model.fga:/app/authorisation_model.fga ports: diff --git a/go.mod b/go.mod index 0572199e9..a56f08639 100644 --- a/go.mod +++ b/go.mod @@ -82,7 +82,7 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions v1.3.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 // indirect - github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 // indirect github.com/Rican7/retry v0.3.1 // indirect github.com/adrg/xdg v0.3.3 // indirect @@ -113,7 +113,7 @@ require ( github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cjlapao/common-go v0.0.39 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect - github.com/creack/pty v1.1.15 // indirect + github.com/creack/pty v1.1.18 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/distribution/reference v0.5.0 // indirect @@ -131,7 +131,7 @@ require ( github.com/getkin/kin-openapi v0.125.0 // indirect github.com/go-goose/goose/v5 v5.0.0-20230421180421-abaee9096e3a // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect - github.com/go-logr/logr v1.4.1 // indirect + github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-macaroon-bakery/macaroonpb v1.0.0 // indirect github.com/go-openapi/jsonpointer v0.20.2 // indirect @@ -147,13 +147,13 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.2.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/renameio v1.0.1 // indirect github.com/google/s2a-go v0.1.7 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/gorilla/schema v1.4.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect @@ -237,7 +237,7 @@ require ( github.com/lestrrat/go-jsval v0.0.0-20161012045717-b1258a10419f // indirect github.com/lestrrat/go-pdebug v0.0.0-20160817063333-2e6eaaa5717f // indirect github.com/lestrrat/go-structinfo v0.0.0-20160308131105-f74c056fe41f // indirect - github.com/lib/pq v1.10.7 // indirect + github.com/lib/pq v1.10.9 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/lunixbochs/vtclean v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -260,7 +260,7 @@ require ( github.com/mittwald/vaultgo v0.1.4 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/sys/mountinfo v0.7.1 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/moby/term v0.5.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect @@ -307,10 +307,10 @@ require ( github.com/xdg-go/stringprep v1.0.4 // indirect github.com/zitadel/oidc/v2 v2.12.0 // indirect go.opencensus.io v0.24.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect + go.opentelemetry.io/otel v1.29.0 // indirect + go.opentelemetry.io/otel/metric v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.29.0 // indirect go.uber.org/atomic v1.11.0 // indirect go.uber.org/mock v0.5.0 // indirect go.uber.org/multierr v1.11.0 // indirect @@ -322,7 +322,7 @@ require ( golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.6.0 // indirect golang.org/x/tools v0.26.0 // indirect - google.golang.org/api v0.154.0 // indirect + google.golang.org/api v0.169.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect google.golang.org/grpc v1.66.0 // indirect @@ -346,6 +346,15 @@ require ( sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) +require github.com/golang-migrate/migrate/v4 v4.17.1 + +require ( + github.com/klauspost/compress v1.17.7 // indirect + github.com/moby/patternmatcher v0.6.0 // indirect + github.com/moby/sys/sequential v0.6.0 // indirect + github.com/shopspring/decimal v1.4.0 // indirect +) + replace ( github.com/altoros/gosigma => github.com/juju/gosigma v0.0.0-20170523021020-a27b59fe2be9 gopkg.in/yaml.v2 => github.com/juju/yaml v0.0.0-20200420012109-12a32b78de07 diff --git a/go.sum b/go.sum index 03618b65d..4b98f0c71 100644 --- a/go.sum +++ b/go.sum @@ -69,8 +69,8 @@ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0 h1:DRiANoJ github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.1.0/go.mod h1:qLIye2hwb/ZouqhpSD9Zn3SJipvpEnz1Ywl3VUk9Y0s= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80= github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= +github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ntlmssp v0.0.0-20211209120228-48547f28849e/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU= github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= @@ -81,10 +81,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/hcsshim v0.9.4 h1:mnUj0ivWy6UzbB1uLFqKR6F+ZyiDc7j4iGgHTpO+5+I= -github.com/Microsoft/hcsshim v0.9.4/go.mod h1:7pLA8lDk46WKDWlVsENo92gC0XFa8rbKfyFRBqxEbCc= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/Rican7/retry v0.3.0/go.mod h1:CxSDrhAyXmTMeEuRAnArMu1FHu48vtfjLREWqVl7Vw0= github.com/Rican7/retry v0.3.1 h1:scY4IbO8swckzoA/11HgBwaZRJEyY9vaNJshcdhp1Mc= @@ -175,8 +173,6 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= -github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= github.com/containerd/containerd v1.6.8 h1:h4dOFDwzHmqFEP754PgfgTeVXFnLiRc6kiqC7tplDJs= github.com/containerd/containerd v1.6.8/go.mod h1:By6p5KqPK0/7/CgO/A6t/Gz+CUYUu2zf1hUaaymVXB0= github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI= @@ -190,15 +186,16 @@ github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSV github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 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= -github.com/creack/pty v1.1.15 h1:cKRCLMj3Ddm54bKSpemfQ8AtYFBhAI2MPmdys22fBdc= -github.com/creack/pty v1.1.15/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= 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/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= +github.com/dhui/dktest v0.4.1 h1:/w+IWuDXVymg3IrRJCHHOkMK10m9aNVMOyD0X12YVTg= +github.com/dhui/dktest v0.4.1/go.mod h1:DdOqcUpL7vgyP4GlF3X3w7HbSlz8cEQzwewPveYEQbA= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= @@ -206,8 +203,8 @@ github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= -github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v24.0.9+incompatible h1:HPGzNmwfLZWdxHqK9/II92pyi1EpYKsAqcl4G0Of9v0= +github.com/docker/docker v24.0.9+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -272,8 +269,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +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-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-macaroon-bakery/macaroon-bakery/v3 v3.0.1 h1:uvQJoKTHrFFu8zxoaopNKedRzwdy3+8H72we4T/5cGs= @@ -317,6 +314,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-migrate/migrate/v4 v4.17.1 h1:4zQ6iqL6t6AiItphxJctQb3cFqWiSpMnX7wLTPnnYO4= +github.com/golang-migrate/migrate/v4 v4.17.1/go.mod h1:m8hinFyWBn0SA4QKHuKh175Pm9wjmxj3S2Mia7dbXzM= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -350,8 +349,8 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -406,8 +405,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfF github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= @@ -739,6 +738,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= +github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= @@ -785,8 +786,8 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lunixbochs/vtclean v0.0.0-20160125035106-4fbf7632a2c6/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= @@ -866,14 +867,16 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mittwald/vaultgo v0.1.4 h1:f+r0H+hgzXL9b9hkOhkFAQMAR3a/RNgqzlqywN+StXo= github.com/mittwald/vaultgo v0.1.4/go.mod h1:MuFKjvIXDjRU8cVxAKS/12JcxxzRCWzbdDcPC8sGdQQ= +github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= +github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs= -github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0= github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU= +github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -899,6 +902,7 @@ github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmt github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU= github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= @@ -989,8 +993,9 @@ github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= +github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -1010,7 +1015,6 @@ github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= @@ -1084,14 +1088,14 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= +go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= +go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= +go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= +go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= +go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= +go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= @@ -1182,6 +1186,8 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= +golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 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= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1384,7 +1390,6 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -1461,8 +1466,8 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= -google.golang.org/api v0.154.0 h1:X7QkVKZBskztmpPKWQXgjJRPA2dJYrL6r+sYPRLj050= -google.golang.org/api v0.154.0/go.mod h1:qhSMkM85hgqiokIYsrRyKxrjfBeIhgl4Z2JmeRkYylc= +google.golang.org/api v0.169.0 h1:QwWPy71FgMWqJN/l6jVlFHUa29a7dcUy02I8o799nPY= +google.golang.org/api v0.169.0/go.mod h1:gpNOiMA2tZ4mf5R9Iwf4rK/Dcz0fbdIgWYWVoxmsyLg= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1602,8 +1607,6 @@ gorm.io/driver/postgres v1.5.9 h1:DkegyItji119OlcaLjqN11kHoUgZ/j13E0jkJZgD6A8= gorm.io/driver/postgres v1.5.9/go.mod h1:DX3GReXH+3FPWGrrgffdvCk3DQ1dwDPdmbenSkweRGI= gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= -gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/auth/oauth2_test.go b/internal/auth/oauth2_test.go index 9c5b18de2..35a5b2b23 100644 --- a/internal/auth/oauth2_test.go +++ b/internal/auth/oauth2_test.go @@ -31,7 +31,7 @@ func setupTestAuthSvc(ctx context.Context, c *qt.C, expiry time.Duration) (*auth db := &db.Database{ DB: jimmtest.PostgresDB(c, time.Now), } - c.Assert(db.Migrate(ctx, false), qt.IsNil) + c.Assert(db.Migrate(ctx), qt.IsNil) sqldb, err := db.DB.DB() c.Assert(err, qt.IsNil) diff --git a/internal/db/applicationoffer_test.go b/internal/db/applicationoffer_test.go index c5938deb7..ff9f922aa 100644 --- a/internal/db/applicationoffer_test.go +++ b/internal/db/applicationoffer_test.go @@ -36,7 +36,7 @@ type testEnvironment struct { } func initTestEnvironment(c *qt.C, db *db.Database) testEnvironment { - err := db.Migrate(context.Background(), true) + err := db.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) env := testEnvironment{} diff --git a/internal/db/auditlog_test.go b/internal/db/auditlog_test.go index 8bad93484..9decee04c 100644 --- a/internal/db/auditlog_test.go +++ b/internal/db/auditlog_test.go @@ -35,7 +35,7 @@ func (s *dbSuite) TestAddAuditLogEntry(c *qt.C) { err := s.Database.AddAuditLogEntry(ctx, &ale) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.AddAuditLogEntry(ctx, &ale) @@ -117,7 +117,7 @@ func (s *dbSuite) TestForEachAuditLogEntry(c *qt.C) { err := s.Database.ForEachAuditLogEntry(context.Background(), db.AuditLogFilter{}, nil) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) for i := range testAuditLogEntries { @@ -159,7 +159,7 @@ func (s *dbSuite) TestDeleteAuditLogsBefore(c *qt.C) { }) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), true) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) // Delete all when none exist @@ -221,7 +221,7 @@ func (s *dbSuite) TestPurgeLogsFromDb(c *qt.C) { IdentityTag: names.NewUserTag("alice@canonical.com").String(), } - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.AddAuditLogEntry(ctx, &ale) c.Assert(err, qt.IsNil) diff --git a/internal/db/cloud_test.go b/internal/db/cloud_test.go index f959bc7f3..7d4954014 100644 --- a/internal/db/cloud_test.go +++ b/internal/db/cloud_test.go @@ -43,7 +43,7 @@ func (s *dbSuite) TestAddCloud(c *qt.C) { err := s.Database.AddCloud(ctx, &cl) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.AddCloud(ctx, &cl) @@ -82,7 +82,7 @@ func (s *dbSuite) TestGetCloud(c *qt.C) { err := s.Database.GetCloud(ctx, &cl) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.GetCloud(ctx, &cl) @@ -123,7 +123,7 @@ func (s *dbSuite) TestGetClouds(c *qt.C) { _, err := s.Database.GetClouds(ctx) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) clouds, err := s.Database.GetClouds(ctx) @@ -177,7 +177,7 @@ func (s *dbSuite) TestUpdateCloud(c *qt.C) { err := s.Database.UpdateCloud(ctx, &cl) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.UpdateCloud(ctx, &cl) @@ -226,7 +226,7 @@ func TestFindRegionUnconfiguredDatabase(t *testing.T) { func (s *dbSuite) TestFindRegionByCloudType(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(ctx, false) + err := s.Database.Migrate(ctx) c.Assert(err, qt.IsNil) env := jimmtest.ParseEnvironment(c, `clouds: @@ -271,7 +271,7 @@ controllers: func (s *dbSuite) TestFindRegionByCloudName(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(ctx, false) + err := s.Database.Migrate(ctx) c.Assert(err, qt.IsNil) env := jimmtest.ParseEnvironment(c, `clouds: @@ -341,7 +341,7 @@ func (s *dbSuite) TestDeleteCloud(c *qt.C) { err := s.Database.DeleteCloud(ctx, &cl) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.AddCloud(ctx, &cl) @@ -379,7 +379,7 @@ func (s *dbSuite) TestDeleteCloudRegionControllerPriority(c *qt.C) { err := s.Database.DeleteCloudRegionControllerPriority(ctx, &crp) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) env := jimmtest.ParseEnvironment(c, `clouds: diff --git a/internal/db/cloudcredential_test.go b/internal/db/cloudcredential_test.go index ae1d541a1..f91d2bdae 100644 --- a/internal/db/cloudcredential_test.go +++ b/internal/db/cloudcredential_test.go @@ -27,7 +27,7 @@ func TestSetCloudCredentialUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestSetCloudCredentialInvalidTag(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -54,7 +54,7 @@ func (s *dbSuite) TestSetCloudCredentialInvalidTag(c *qt.C) { } func (s *dbSuite) TestSetCloudCredential(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -90,7 +90,7 @@ func (s *dbSuite) TestSetCloudCredential(c *qt.C) { } func (s *dbSuite) TestSetCloudCredentialUpdate(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -159,7 +159,7 @@ func TestGetCloudCredentialUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestGetCloudCredential(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -276,7 +276,7 @@ func (s *dbSuite) TestForEachCloudCredential(c *qt.C) { ctx := context.Background() env := jimmtest.ParseEnvironment(c, forEachCloudCredentialEnv) - err := s.Database.Migrate(ctx, false) + err := s.Database.Migrate(ctx) c.Assert(err, qt.IsNil) env.PopulateDB(c, s.Database) diff --git a/internal/db/clouddefaults_test.go b/internal/db/clouddefaults_test.go index f92d5c5ca..bfcc70bdf 100644 --- a/internal/db/clouddefaults_test.go +++ b/internal/db/clouddefaults_test.go @@ -19,7 +19,7 @@ import ( func (s *dbSuite) TestModelDefaults(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(ctx, true) + err := s.Database.Migrate(ctx) c.Assert(err, qt.Equals, nil) u, err := dbmodel.NewIdentity("bob@canonical.com") diff --git a/internal/db/controller_test.go b/internal/db/controller_test.go index 4437942f7..e1049b07a 100644 --- a/internal/db/controller_test.go +++ b/internal/db/controller_test.go @@ -26,7 +26,7 @@ func TestAddControllerUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestAddController(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) cloud := dbmodel.Cloud{ @@ -57,7 +57,7 @@ func (s *dbSuite) TestAddController(c *qt.C) { } func (s *dbSuite) TestGetController(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) cloud := dbmodel.Cloud{ @@ -134,7 +134,7 @@ controllers: func (s *dbSuite) TestForEachController(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) env := jimmtest.ParseEnvironment(c, testForEachControllerEnv) @@ -169,7 +169,7 @@ func TestUpdateControllerUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestUpdateController(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) cloud := dbmodel.Cloud{ @@ -219,7 +219,7 @@ func (s *dbSuite) TestUpdateController(c *qt.C) { } func (s *dbSuite) TestDeleteController(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) cloud := dbmodel.Cloud{ @@ -317,7 +317,7 @@ models: func (s *dbSuite) TestForEachControllerModel(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) env := jimmtest.ParseEnvironment(c, testForEachControllerModelEnv) diff --git a/internal/db/db.go b/internal/db/db.go index d06c46e1e..1ff91257d 100644 --- a/internal/db/db.go +++ b/internal/db/db.go @@ -6,15 +6,29 @@ package db import ( "context" "database/sql" + "embed" + stderr "errors" "fmt" "path" "sync/atomic" "time" + "github.com/golang-migrate/migrate/v4" + "github.com/golang-migrate/migrate/v4/database/postgres" + "github.com/golang-migrate/migrate/v4/source/iofs" + "github.com/juju/zaputil/zapctx" + "go.uber.org/zap" "gorm.io/gorm" "github.com/canonical/jimm/v3/internal/dbmodel" "github.com/canonical/jimm/v3/internal/errors" + "github.com/canonical/jimm/v3/internal/logger" +) + +// Use a custom table name so that we don't run into collisions when OpenFGA or other tools +// are using the same DB as JIMM in our Docker Compose setup. +const ( + migrationTableName = "jimm_schema_migrations" ) // A Database provides access to the database model. A Database instance @@ -50,56 +64,105 @@ func (d *Database) Transaction(f func(*Database) error) error { } // Migrate migrates the configured database to have the structure required -// by the current data model. Unless forced the migration will only be -// performed if there is either no current database, or the major version -// of the current database is the same as the target database. If the -// current database is incompatible then an error with a code of -// errors.CodeServerConfiguration will be returned. If force is requested -// then the migration will be performed no matter what the current version -// is. The force parameter should only be set when the migration is -// initiated by a user request. -func (d *Database) Migrate(ctx context.Context, force bool) error { +// by the current data model. If the database is not configured then an error +// with a code of errors.CodeServerConfiguration will be returned. +func (d *Database) Migrate(ctx context.Context) error { const op = errors.Op("db.Migrate") if d == nil || d.DB == nil { return errors.E(op, errors.CodeServerConfiguration, "database not configured") } + + err := d.migrateFromSource(ctx, dbmodel.SQL, path.Join("sql", d.DB.Name())) + if err != nil { + return errors.E(op, err) + } + return nil +} + +func (d *Database) migrateFromSource(ctx context.Context, fs embed.FS, sqlPath string) error { + sqlDir, err := iofs.New(fs, sqlPath) + if err != nil { + return fmt.Errorf("unable to create new sql filesys: %w", err) + } + db := d.DB.WithContext(ctx) - schema, _ := dbmodel.SQL.ReadFile(path.Join("sql", db.Name(), "versions.sql")) - if err := db.Exec(string(schema)).Error; err != nil { - return errors.E(op, dbError(err)) + sqlDB, err := db.DB() + if err != nil { + return fmt.Errorf("failed to obtain raw DB: %w", err) + } + conn, err := sqlDB.Conn(ctx) + if err != nil { + return fmt.Errorf("failed to obtain DB conn: %w", err) } - for { - v := dbmodel.Version{Component: dbmodel.Component, Major: 1, Minor: 0} - if err := db.FirstOrCreate(&v).Error; err != nil { - return errors.E(op, dbError(err)) - } - if dbmodel.Major == v.Major && dbmodel.Minor <= v.Minor { - // The database is already at, or past, our current version. - // Nothing to do. - atomic.StoreUint32(&d.migrated, 1) - return nil - } - if v.Major != dbmodel.Major && !force { - return errors.E(op, errors.CodeServerConfiguration, fmt.Sprintf("database has incompatible version %d.%d", v.Major, v.Minor)) + driver, err := postgres.WithConnection(ctx, conn, &postgres.Config{MigrationsTable: migrationTableName}) + if err != nil { + return fmt.Errorf("unable to create new driver instance: %w", err) + } + + // DB name is left blank because it is contained in the driver/DB connection. + m, err := migrate.NewWithInstance("iofs", sqlDir, "", driver) + if err != nil { + return fmt.Errorf("unable to create new migrator: %w", err) + } + defer m.Close() + + // Setup custom logger for consistent output. + logger := logger.MigrationLogger{Logger: zapctx.Logger(ctx)} + m.Log = logger + + if err := d.handleDeprecatedMigrations(ctx, m); err != nil { + return fmt.Errorf("failed to handle deprecated migrations: %w", err) + } + + v, dirty, err := m.Version() + if err != nil { + if !stderr.Is(err, migrate.ErrNilVersion) { + return fmt.Errorf("failed to get db version: %w", err) } - // The major versions are unchanged, the database can be migrated. - v.Minor += 1 - schema, err := dbmodel.SQL.ReadFile(path.Join("sql", db.Name(), fmt.Sprintf("%d_%d.sql", v.Major, v.Minor))) - if err != nil { - return errors.E(op, err) + } + + if dirty { + // nolint:gosec + workingVersion := int(v) - 1 + zapctx.Info(ctx, "dirty database, reverting version", zap.Int("version", workingVersion)) + if err := m.Force(workingVersion); err != nil { + return fmt.Errorf("failed to fix dirty db version: %w", err) } + } - err = db.Transaction(func(tx *gorm.DB) error { - if err := tx.Exec(string(schema)).Error; err != nil { - return err - } - return nil - }) - if err != nil { - return errors.E(op, dbError(err)) + if err := m.Up(); err != nil { + if !stderr.Is(err, migrate.ErrNoChange) { + return fmt.Errorf("failed to migrate db: %w", err) } } + + atomic.StoreUint32(&d.migrated, 1) + return nil +} + +// This method is used for handling deployments that are live when we made the +// switch from a home-grown migration library to golang-migrate. To avoid running +// migrations twice, we check if the old "versions" table exists and make golang-migrate +// aware of which migrations have been run using the Force() method. +func (d *Database) handleDeprecatedMigrations(ctx context.Context, m *migrate.Migrate) error { + var version int + err := d.DB.Raw("SELECT minor FROM versions;").Row().Scan(&version) + if err != nil { + // The versions table may already be deleted. Other errors are ignored intentionally. + zapctx.Debug(ctx, "no minor version from deprecated migrations table", zap.Error(err)) + //nolint:nilerr + return nil + } + if version == 0 { + return nil + } + zapctx.Debug(ctx, "forcing db version", zap.Int("version", version)) + err = m.Force(version) + if err != nil { + return err + } + return nil } // ready checks that the database is ready to accept requests. An error is diff --git a/internal/db/db_test.go b/internal/db/db_test.go index 4901dcdd5..4b27ccace 100644 --- a/internal/db/db_test.go +++ b/internal/db/db_test.go @@ -4,15 +4,42 @@ package db_test import ( "context" + "embed" "testing" qt "github.com/frankban/quicktest" + "github.com/golang-migrate/migrate/v4" + "github.com/golang-migrate/migrate/v4/database/postgres" + "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/canonical/jimm/v3/internal/db" "github.com/canonical/jimm/v3/internal/dbmodel" "github.com/canonical/jimm/v3/internal/errors" ) +//go:embed testdata/invalidmigrations/*.sql +var invalidSQL embed.FS + +//go:embed testdata/validmigrations/*.sql +var validSQL embed.FS + +func newTestMigrator(c *qt.C, d *db.Database, fs embed.FS, sqlPath string) *migrate.Migrate { + sqlDir, err := iofs.New(fs, sqlPath) + c.Assert(err, qt.IsNil) + + sqlDB, err := d.DB.DB() + c.Assert(err, qt.IsNil) + + driver, err := postgres.WithInstance(sqlDB, &postgres.Config{MigrationsTable: db.MigrationTableName}) + c.Assert(err, qt.IsNil) + + m, err := migrate.NewWithInstance("iofs", sqlDir, "", driver) + c.Assert(err, qt.IsNil) + c.Cleanup(func() { m.Close() }) + + return m +} + // dbSuite contains a suite of database tests that are run against // different database engines. type dbSuite struct { @@ -21,20 +48,45 @@ type dbSuite struct { func (s *dbSuite) TestMigrate(c *qt.C) { // Migrate from an empty database should work. - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) // Attempting to migrate to the version that is already there should // also work. - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) + c.Assert(err, qt.IsNil) +} + +// TestFailedMigration verifies a failed migration will cause a dirty migration +// that when fixed should automatically work. +func (s *dbSuite) TestFailedMigration(c *qt.C) { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + err := s.Database.MigrateFromSource(ctx, invalidSQL, "testdata/invalidmigrations") + c.Assert(err, qt.Not(qt.IsNil)) + + m := newTestMigrator(c, s.Database, invalidSQL, "testdata/invalidmigrations") + v, dirty, err := m.Version() + c.Assert(err, qt.IsNil) + c.Assert(dirty, qt.IsTrue) + c.Assert(v, qt.Equals, uint(2)) + + err = s.Database.MigrateFromSource(ctx, validSQL, "testdata/validmigrations") + c.Assert(err, qt.IsNil) + + m = newTestMigrator(c, s.Database, validSQL, "testdata/validmigrations") + v, dirty, err = m.Version() c.Assert(err, qt.IsNil) + c.Assert(dirty, qt.IsFalse) + c.Assert(v, qt.Equals, uint(3)) } func TestMigrateUnconfiguredDatabase(t *testing.T) { c := qt.New(t) var database db.Database - err := database.Migrate(context.Background(), false) + err := database.Migrate(context.Background()) c.Check(err, qt.ErrorMatches, `database not configured`) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeServerConfiguration) } @@ -57,7 +109,7 @@ func (s *dbSuite) TestTransaction(c *qt.C) { c.Check(err, qt.ErrorMatches, `upgrade in progress`) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) i, err := dbmodel.NewIdentity("bob@canonical.com") c.Assert(err, qt.IsNil) diff --git a/internal/db/export_test.go b/internal/db/export_test.go index d3a632218..1cab6ad6a 100644 --- a/internal/db/export_test.go +++ b/internal/db/export_test.go @@ -2,6 +2,11 @@ package db +import ( + "context" + "embed" +) + var ( JwksKind = jwksKind JwksPublicKeyTag = jwksPublicKeyTag @@ -11,4 +16,9 @@ var ( OAuthKeyTag = oauthKeyTag OAuthSessionStoreSecretTag = oauthSessionStoreSecretTag NewUUID = &newUUID + MigrationTableName = migrationTableName ) + +func (d *Database) MigrateFromSource(ctx context.Context, fs embed.FS, sqlPath string) error { + return d.migrateFromSource(ctx, fs, sqlPath) +} diff --git a/internal/db/group_test.go b/internal/db/group_test.go index 82df3fdfa..e1f9491e6 100644 --- a/internal/db/group_test.go +++ b/internal/db/group_test.go @@ -37,7 +37,7 @@ func (s *dbSuite) TestAddGroup(c *qt.C) { _, err := s.Database.AddGroup(ctx, "test-group") c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) groupEntry, err := s.Database.AddGroup(ctx, "test-group") @@ -58,7 +58,7 @@ func (s *dbSuite) TestAddGroup(c *qt.C) { } func (s *dbSuite) TestCountGroups(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) addNGroups := 10 @@ -82,7 +82,7 @@ func (s *dbSuite) TestGetGroup(c *qt.C) { }) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) group := &dbmodel.GroupEntry{ @@ -125,7 +125,7 @@ func (s *dbSuite) TestUpdateGroupName(c *qt.C) { err := s.Database.UpdateGroupName(context.Background(), "test-group", "new-name") c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.UpdateGroupName(context.Background(), "test-group", "new-name") @@ -156,7 +156,7 @@ func (s *dbSuite) TestRemoveGroup(c *qt.C) { err := s.Database.RemoveGroup(context.Background(), &dbmodel.GroupEntry{Name: "test-group"}) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeNotFound) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) ge := &dbmodel.GroupEntry{ @@ -183,7 +183,7 @@ func (s *dbSuite) TestRemoveGroup(c *qt.C) { } func (s *dbSuite) TestListGroups(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) addNGroups := 10 diff --git a/internal/db/identity_test.go b/internal/db/identity_test.go index e2bd12f94..b3977a4e3 100644 --- a/internal/db/identity_test.go +++ b/internal/db/identity_test.go @@ -33,7 +33,7 @@ func (s *dbSuite) TestGetIdentity(c *qt.C) { c.Check(err, qt.ErrorMatches, `upgrade in progress`) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(ctx, false) + err = s.Database.Migrate(ctx) c.Assert(err, qt.IsNil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -83,7 +83,7 @@ func (s *dbSuite) TestUpdateIdentity(c *qt.C) { c.Check(err, qt.ErrorMatches, `upgrade in progress`) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(ctx, false) + err = s.Database.Migrate(ctx) c.Assert(err, qt.IsNil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -133,7 +133,7 @@ func TestGetIdentityCloudCredentialsUnconfiguredDatabase(t *testing.T) { func (s *dbSuite) TestGetIdentityCloudCredentials(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(ctx, false) + err := s.Database.Migrate(ctx) c.Assert(err, qt.IsNil) i, err := dbmodel.NewIdentity("idontexist") @@ -184,7 +184,7 @@ func (s *dbSuite) TestGetIdentityCloudCredentials(c *qt.C) { } func (s *dbSuite) TestListIdentities(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) for i := range 10 { diff --git a/internal/db/model_test.go b/internal/db/model_test.go index 4b3a1f8b9..92b6b8735 100644 --- a/internal/db/model_test.go +++ b/internal/db/model_test.go @@ -28,7 +28,7 @@ func TestAddModelUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestAddModel(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -90,7 +90,7 @@ func (s *dbSuite) TestAddModel(c *qt.C) { } func (s *dbSuite) TestGetModel(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) u, err := dbmodel.NewIdentity("bob@canonical.com") @@ -182,7 +182,7 @@ func (s *dbSuite) TestGetModel(c *qt.C) { } func (s *dbSuite) TestUpdateModel(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) i, err := dbmodel.NewIdentity("bob@canonical.com") @@ -249,7 +249,7 @@ func TestDeleteModelUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestDeleteModel(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) i, err := dbmodel.NewIdentity("bob@canonical.com") @@ -312,7 +312,7 @@ func (s *dbSuite) TestDeleteModel(c *qt.C) { } func (s *dbSuite) TestGetModelsUsingCredential(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) i, err := dbmodel.NewIdentity("bob@canonical.com") @@ -468,7 +468,7 @@ models: func (s *dbSuite) TestForEachModel(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) env := jimmtest.ParseEnvironment(c, testForEachModelEnv) @@ -554,7 +554,7 @@ func TestGetModelsByUUIDlUnconfiguredDatabase(t *testing.T) { func (s *dbSuite) TestGetModelsByUUID(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) env := jimmtest.ParseEnvironment(c, testGetModelsByUUIDEnv) @@ -580,7 +580,7 @@ func (s *dbSuite) TestGetModelsByUUID(c *qt.C) { } func (s *dbSuite) TestGetModelsByController(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) cloud := dbmodel.Cloud{ @@ -692,7 +692,7 @@ models: ` func (s *dbSuite) TestCountModelsByController(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) env := jimmtest.ParseEnvironment(c, testCountModelsByControllerEnv) diff --git a/internal/db/resource_test.go b/internal/db/resource_test.go index 03e45149c..ecf645efd 100644 --- a/internal/db/resource_test.go +++ b/internal/db/resource_test.go @@ -68,7 +68,7 @@ func SetupDB(c *qt.C, database *db.Database) (dbmodel.Model, dbmodel.Controller, func (s *dbSuite) TestGetResources(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) res, err := s.Database.ListResources(ctx, 10, 0, "", "") c.Assert(err, qt.Equals, nil) @@ -95,7 +95,7 @@ func (s *dbSuite) TestGetResources(c *qt.C) { func (s *dbSuite) TestGetResourcesWithNameTypeFilter(c *qt.C) { ctx := context.Background() - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) // create one model, one controller, one cloud model, controller, cloud, sva := SetupDB(c, s.Database) diff --git a/internal/db/role_test.go b/internal/db/role_test.go index 2d3f23370..d1b0d8767 100644 --- a/internal/db/role_test.go +++ b/internal/db/role_test.go @@ -26,7 +26,7 @@ func (s *dbSuite) TestAddRole(c *qt.C) { _, err := s.Database.AddRole(ctx, "test-role") c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) roleEntry, err := s.Database.AddRole(ctx, "test-role") @@ -55,7 +55,7 @@ func (s *dbSuite) TestGetRole(c *qt.C) { err := s.Database.GetRole(context.Background(), &dbmodel.RoleEntry{}) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) role := &dbmodel.RoleEntry{} @@ -84,7 +84,7 @@ func (s *dbSuite) TestGetRole(c *qt.C) { } func (s *dbSuite) TestUpdateRoleName(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) err = s.Database.UpdateRoleName(context.Background(), "blah", "blah") @@ -118,7 +118,7 @@ func (s *dbSuite) TestRemoveRole(c *qt.C) { err := s.Database.RemoveRole(context.Background(), &dbmodel.RoleEntry{Name: "test-role"}) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeNotFound) - err = s.Database.Migrate(context.Background(), false) + err = s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) re := &dbmodel.RoleEntry{ @@ -145,7 +145,7 @@ func (s *dbSuite) TestRemoveRole(c *qt.C) { } func (s *dbSuite) TestListRole(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) addNRoles := 10 @@ -189,7 +189,7 @@ func (s *dbSuite) TestListRole(c *qt.C) { } func (s *dbSuite) TestCountRoles(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) addNRoles := 10 diff --git a/internal/db/rootkeys_test.go b/internal/db/rootkeys_test.go index 28909a999..75460013d 100644 --- a/internal/db/rootkeys_test.go +++ b/internal/db/rootkeys_test.go @@ -42,7 +42,7 @@ func TestInsertKeyUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestInsertKeyGetKey(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) _, err = s.Database.GetKey([]byte("test-id")) @@ -74,7 +74,7 @@ func TestFindLatestKeyUnconfiguredDatabase(t *testing.T) { } func (s *dbSuite) TestFindLatestKey(c *qt.C) { - err := s.Database.Migrate(context.Background(), false) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.IsNil) now := time.Now().UTC().Round(time.Millisecond) diff --git a/internal/db/secrets_test.go b/internal/db/secrets_test.go index 38baa2776..2cfc423bc 100644 --- a/internal/db/secrets_test.go +++ b/internal/db/secrets_test.go @@ -19,7 +19,7 @@ import ( var testTime = time.Date(2013, 7, 26, 0, 0, 0, 0, time.UTC) func (s *dbSuite) TestInsertSecret(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) u := dbmodel.Secret{ @@ -39,7 +39,7 @@ func (s *dbSuite) TestInsertSecret(c *qt.C) { } func (s *dbSuite) TestUpsertSecret(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() @@ -66,7 +66,7 @@ func (s *dbSuite) TestUpsertSecret(c *qt.C) { } func (s *dbSuite) TestGetSecret(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() @@ -85,7 +85,7 @@ func (s *dbSuite) TestGetSecret(c *qt.C) { } func (s *dbSuite) TestGetSecretFailsWithoutTypeAndTag(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() secret := dbmodel.Secret{} @@ -93,7 +93,7 @@ func (s *dbSuite) TestGetSecretFailsWithoutTypeAndTag(c *qt.C) { } func (s *dbSuite) TestDeleteSecretFailsWithoutTypeAndTag(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() @@ -102,7 +102,7 @@ func (s *dbSuite) TestDeleteSecretFailsWithoutTypeAndTag(c *qt.C) { } func (s *dbSuite) TestDeleteSecret(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() @@ -121,7 +121,7 @@ func (s *dbSuite) TestDeleteSecret(c *qt.C) { } func (s *dbSuite) TestPutAndGetCloudCredential(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() cloudCred := names.NewCloudCredentialTag("foo/bar/bob") @@ -140,7 +140,7 @@ func (s *dbSuite) TestPutAndGetCloudCredential(c *qt.C) { } func (s *dbSuite) TestPutAndGetControllerCredential(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() controllerName := "beef1beef2-0000-0000-000011112222" @@ -159,7 +159,7 @@ func (s *dbSuite) TestPutAndGetControllerCredential(c *qt.C) { } func (s *dbSuite) TestGetMissingControllerCredentialDoesNotError(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() controllerName := "beef1beef2-0000-0000-000011112222" @@ -197,7 +197,7 @@ func getJWKS(c *qt.C) jwk.Set { } func (s *dbSuite) TestPutAndGetJWKS(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() jwks := getJWKS(c) @@ -225,7 +225,7 @@ func (s *dbSuite) TestPutAndGetJWKS(c *qt.C) { } func (s *dbSuite) TestPutAndGetJwksExpiry(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() expiryTime := time.Date(2023, 7, 26, 0, 0, 0, 0, time.UTC) @@ -243,7 +243,7 @@ func (s *dbSuite) TestPutAndGetJwksExpiry(c *qt.C) { } func (s *dbSuite) TestPutAndGetJwksPrivateKey(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() pem := []byte("123") @@ -261,7 +261,7 @@ func (s *dbSuite) TestPutAndGetJwksPrivateKey(c *qt.C) { } func (s *dbSuite) TestCleanupJWKS(c *qt.C) { - err := s.Database.Migrate(context.Background(), true) + err := s.Database.Migrate(context.Background()) c.Assert(err, qt.Equals, nil) ctx := context.Background() pem := []byte("123") diff --git a/internal/db/testdata/invalidmigrations/001_initial.up.sql b/internal/db/testdata/invalidmigrations/001_initial.up.sql new file mode 100644 index 000000000..a7c726c60 --- /dev/null +++ b/internal/db/testdata/invalidmigrations/001_initial.up.sql @@ -0,0 +1,6 @@ +-- initialises an empty database. + +CREATE TABLE IF NOT EXISTS test ( + id BIGSERIAL PRIMARY KEY, + time TIMESTAMP WITH TIME ZONE +); diff --git a/internal/db/testdata/invalidmigrations/002_add_invalid_table.up.sql b/internal/db/testdata/invalidmigrations/002_add_invalid_table.up.sql new file mode 100644 index 000000000..911c50079 --- /dev/null +++ b/internal/db/testdata/invalidmigrations/002_add_invalid_table.up.sql @@ -0,0 +1,6 @@ +-- adds an invalid table. + +CREATE TABLE IF NOT EXISTS invalid ( + id BIGSERIAL PRIMARY KEY, + time INVALIDTYPE +); diff --git a/internal/db/testdata/invalidmigrations/003_add_another_table.up.sql b/internal/db/testdata/invalidmigrations/003_add_another_table.up.sql new file mode 100644 index 000000000..1975577f0 --- /dev/null +++ b/internal/db/testdata/invalidmigrations/003_add_another_table.up.sql @@ -0,0 +1,6 @@ +-- adds an controller table. + +CREATE TABLE IF NOT EXISTS controller ( + id BIGSERIAL PRIMARY KEY, + name TEXT +); diff --git a/internal/db/testdata/validmigrations/001_initial.up.sql b/internal/db/testdata/validmigrations/001_initial.up.sql new file mode 100644 index 000000000..a7c726c60 --- /dev/null +++ b/internal/db/testdata/validmigrations/001_initial.up.sql @@ -0,0 +1,6 @@ +-- initialises an empty database. + +CREATE TABLE IF NOT EXISTS test ( + id BIGSERIAL PRIMARY KEY, + time TIMESTAMP WITH TIME ZONE +); diff --git a/internal/db/testdata/validmigrations/002_add_table.up.sql b/internal/db/testdata/validmigrations/002_add_table.up.sql new file mode 100644 index 000000000..013df327c --- /dev/null +++ b/internal/db/testdata/validmigrations/002_add_table.up.sql @@ -0,0 +1,5 @@ +-- adds a valid table. + +CREATE TABLE IF NOT EXISTS valid ( + id BIGSERIAL PRIMARY KEY +); diff --git a/internal/db/testdata/validmigrations/003_add_another_table.up.sql b/internal/db/testdata/validmigrations/003_add_another_table.up.sql new file mode 100644 index 000000000..a1a03e739 --- /dev/null +++ b/internal/db/testdata/validmigrations/003_add_another_table.up.sql @@ -0,0 +1,6 @@ +-- adds a controller table. + +CREATE TABLE IF NOT EXISTS controller ( + id BIGSERIAL PRIMARY KEY, + name TEXT +); diff --git a/internal/dbmodel/gorm_test.go b/internal/dbmodel/gorm_test.go index e636dced3..4d35a6f79 100644 --- a/internal/dbmodel/gorm_test.go +++ b/internal/dbmodel/gorm_test.go @@ -18,7 +18,7 @@ import ( // migrations for those objects. func gormDB(t testing.TB) *gorm.DB { database := db.Database{DB: jimmtest.PostgresDB(t, nil)} - err := database.Migrate(context.Background(), false) + err := database.Migrate(context.Background()) if err != nil { t.Fail() } diff --git a/internal/dbmodel/sql/migrations.md b/internal/dbmodel/sql/migrations.md new file mode 100644 index 000000000..50cb00c94 --- /dev/null +++ b/internal/dbmodel/sql/migrations.md @@ -0,0 +1,18 @@ +# Notes + +Migrations are applied using [golang-migrate](https://github.com/golang-migrate/migrate). +Previously migrations were applied using a home-grown solution and a `versions` table. +The switch to golang-migrate was done to simplify our code. + +To cater for existing deployments, we handle the case that the `versions` table still +exists and "force" the new migration tool to align with the old. + +No "down" migrations are used currently. We aim to work with the philosophy that application +changes should be done such that we deprecate the use of any tables/columns, deploy these changes +and then later create a migration to make permanent changes to the DB. Ideally always moving +migrations forwards and never backwards. + +By default, golang-migrate does not run migrations in a transactions. +**But**, the [postgres](https://github.com/golang-migrate/migrate/blob/master/database/postgres/README.md#multi-statement-mode) driver has slightly unique behavior - "running multiple SQL statements in one Exec executes them inside a transaction". +So each migration file is in fact run in a transaction when using PostgreSQL. To be more explicit, +one can wrap the migration file with BEGIN/COMMIT instructions. diff --git a/internal/dbmodel/sql/postgres/1_1.sql b/internal/dbmodel/sql/postgres/001_initial.up.sql similarity index 98% rename from internal/dbmodel/sql/postgres/1_1.sql rename to internal/dbmodel/sql/postgres/001_initial.up.sql index df8bf3c73..975bda15c 100644 --- a/internal/dbmodel/sql/postgres/1_1.sql +++ b/internal/dbmodel/sql/postgres/001_initial.up.sql @@ -1,4 +1,4 @@ --- 1_1.sql initialises an empty database. +-- initialises an empty database. CREATE TABLE IF NOT EXISTS audit_log ( id BIGSERIAL PRIMARY KEY, @@ -284,6 +284,3 @@ CREATE TABLE IF NOT EXISTS groups ( ); CREATE INDEX IF NOT EXISTS idx_group_deleted_at ON groups (deleted_at); CREATE INDEX IF NOT EXISTS idx_group_name ON groups (name); - -UPDATE versions SET major=1, minor=1 WHERE component='jimmdb'; - diff --git a/internal/dbmodel/sql/postgres/1_2.sql b/internal/dbmodel/sql/postgres/002_add_secrets.up.sql similarity index 66% rename from internal/dbmodel/sql/postgres/1_2.sql rename to internal/dbmodel/sql/postgres/002_add_secrets.up.sql index 9deefe206..7523d08c9 100644 --- a/internal/dbmodel/sql/postgres/1_2.sql +++ b/internal/dbmodel/sql/postgres/002_add_secrets.up.sql @@ -1,4 +1,4 @@ --- 1_2.sql is a migration that adds a secrets table. +-- adds a secrets table. CREATE TABLE IF NOT EXISTS secrets ( id BIGSERIAL PRIMARY KEY, @@ -8,5 +8,3 @@ CREATE TABLE IF NOT EXISTS secrets ( data JSONB ); CREATE UNIQUE INDEX IF NOT EXISTS idx_secret_name ON secrets (type, tag); - -UPDATE versions SET major=1, minor=2 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_3.sql b/internal/dbmodel/sql/postgres/003_cloud_credentials_cascade_on_delete.up.sql similarity index 52% rename from internal/dbmodel/sql/postgres/1_3.sql rename to internal/dbmodel/sql/postgres/003_cloud_credentials_cascade_on_delete.up.sql index 5d64bdfc8..2c12d0aed 100644 --- a/internal/dbmodel/sql/postgres/1_3.sql +++ b/internal/dbmodel/sql/postgres/003_cloud_credentials_cascade_on_delete.up.sql @@ -1,4 +1,4 @@ --- 1_3.sql is a migration that alters the foreign key relationship `cloud_credentials.cloud_name -> clouds.name` to a cascade on-delete. +-- alters the foreign key relationship `cloud_credentials.cloud_name -> clouds.name` to a cascade on-delete. ALTER TABLE cloud_credentials DROP CONSTRAINT cloud_credentials_cloud_name_fkey, @@ -6,5 +6,3 @@ ALTER TABLE cloud_credentials FOREIGN KEY (cloud_name) REFERENCES clouds(name) ON DELETE CASCADE; - -UPDATE versions SET major=1, minor=3 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_4.sql b/internal/dbmodel/sql/postgres/004_remove_access_tables.up.sql similarity index 58% rename from internal/dbmodel/sql/postgres/1_4.sql rename to internal/dbmodel/sql/postgres/004_remove_access_tables.up.sql index d880891a1..da3ce86bd 100644 --- a/internal/dbmodel/sql/postgres/1_4.sql +++ b/internal/dbmodel/sql/postgres/004_remove_access_tables.up.sql @@ -1,9 +1,7 @@ --- 1_4.sql is a migration that removes unused tables and columns previously used for access checks. +-- removes unused tables and columns previously used for access checks. DROP TABLE IF EXISTS user_application_offer_access; DROP TABLE IF EXISTS user_cloud_access; DROP TABLE IF EXISTS user_model_access; ALTER TABLE users DROP COLUMN controller_access; ALTER TABLE users DROP COLUMN audit_log_access; - -UPDATE versions SET major=1, minor=4 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/005_add_migrating_controller_column.up.sql b/internal/dbmodel/sql/postgres/005_add_migrating_controller_column.up.sql new file mode 100644 index 000000000..95d79472d --- /dev/null +++ b/internal/dbmodel/sql/postgres/005_add_migrating_controller_column.up.sql @@ -0,0 +1,3 @@ +-- adds a column necessary for model migrations + +ALTER TABLE models ADD COLUMN migration_controller_id INTEGER REFERENCES controllers (id); diff --git a/internal/dbmodel/sql/postgres/1_6.sql b/internal/dbmodel/sql/postgres/006_add_access_tokens_and_update_users_table.up.sql similarity index 92% rename from internal/dbmodel/sql/postgres/1_6.sql rename to internal/dbmodel/sql/postgres/006_add_access_tokens_and_update_users_table.up.sql index b3d4bd28e..4a5311333 100644 --- a/internal/dbmodel/sql/postgres/1_6.sql +++ b/internal/dbmodel/sql/postgres/006_add_access_tokens_and_update_users_table.up.sql @@ -1,5 +1,6 @@ --- 1_6.sql is a migration that adds access tokens to the user table --- and is a migration that renames `user` to `identity`. +-- adds access tokens to the user table +-- and renames `user` to `identity`. + ALTER TABLE users ADD COLUMN access_token TEXT; ALTER TABLE users ADD COLUMN refresh_token TEXT; ALTER TABLE users ADD COLUMN access_token_expiry TIMESTAMP WITH TIME ZONE; @@ -38,5 +39,3 @@ ALTER INDEX IF EXISTS idx_audit_log_user_tag RENAME TO idx_audit_log_identity_ta -- - user_application_offer_access -- - user_cloud_access -- - user_model_access - -UPDATE versions SET major=1, minor=6 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/007_add_uuid_to_groups.up.sql b/internal/dbmodel/sql/postgres/007_add_uuid_to_groups.up.sql new file mode 100644 index 000000000..5c1c33222 --- /dev/null +++ b/internal/dbmodel/sql/postgres/007_add_uuid_to_groups.up.sql @@ -0,0 +1,3 @@ +-- adds a UUID column to the groups table. + +ALTER TABLE groups ADD COLUMN uuid TEXT NOT NULL UNIQUE; diff --git a/internal/dbmodel/sql/postgres/008_add_tls_hostname_to_controllers.up.sql b/internal/dbmodel/sql/postgres/008_add_tls_hostname_to_controllers.up.sql new file mode 100644 index 000000000..2950c1b15 --- /dev/null +++ b/internal/dbmodel/sql/postgres/008_add_tls_hostname_to_controllers.up.sql @@ -0,0 +1,3 @@ +-- adds a tls_hostname column to the controller table. + +ALTER TABLE controllers ADD COLUMN tls_hostname TEXT; diff --git a/internal/dbmodel/sql/postgres/009_remove_controller_soft_delete.up.sql b/internal/dbmodel/sql/postgres/009_remove_controller_soft_delete.up.sql new file mode 100644 index 000000000..f728f542f --- /dev/null +++ b/internal/dbmodel/sql/postgres/009_remove_controller_soft_delete.up.sql @@ -0,0 +1,5 @@ +-- deletes soft-deleted controllers and drops the +-- deleted_at column from the controllers table. + +DELETE FROM controllers WHERE deleted_at IS NOT null; +ALTER TABLE controllers DROP COLUMN deleted_at; diff --git a/internal/dbmodel/sql/postgres/1_10.sql b/internal/dbmodel/sql/postgres/010_stricter_contraints_on_model_names.up.sql similarity index 52% rename from internal/dbmodel/sql/postgres/1_10.sql rename to internal/dbmodel/sql/postgres/010_stricter_contraints_on_model_names.up.sql index 453fb7460..50818db54 100644 --- a/internal/dbmodel/sql/postgres/1_10.sql +++ b/internal/dbmodel/sql/postgres/010_stricter_contraints_on_model_names.up.sql @@ -1,6 +1,4 @@ --- 1_10.sql is a migration that enforces a stricter uniqueness --- constraint on model names. +-- enforces a stricter uniqueness constraint on model names. + ALTER TABLE models DROP CONSTRAINT models_controller_id_owner_identity_name_name_key; ALTER TABLE models ADD CONSTRAINT unique_model_names UNIQUE(owner_identity_name, name); - -UPDATE versions SET major=1, minor=10 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/011_unique_offer_urls.up.sql b/internal/dbmodel/sql/postgres/011_unique_offer_urls.up.sql new file mode 100644 index 000000000..bfb090253 --- /dev/null +++ b/internal/dbmodel/sql/postgres/011_unique_offer_urls.up.sql @@ -0,0 +1,3 @@ +-- enforces uniqueness on URLs in application offers. + +ALTER TABLE application_offers ADD UNIQUE (url); diff --git a/internal/dbmodel/sql/postgres/012_remove_group_soft_delete.up.sql b/internal/dbmodel/sql/postgres/012_remove_group_soft_delete.up.sql new file mode 100644 index 000000000..8a28d325e --- /dev/null +++ b/internal/dbmodel/sql/postgres/012_remove_group_soft_delete.up.sql @@ -0,0 +1,4 @@ +-- deletes soft-deleted groups and drops the deleted_at column from the groups table. + +DELETE FROM groups WHERE deleted_at IS NOT null; +ALTER TABLE groups DROP COLUMN deleted_at; diff --git a/internal/dbmodel/sql/postgres/1_13.sql b/internal/dbmodel/sql/postgres/013_add_roles.up.sql similarity index 60% rename from internal/dbmodel/sql/postgres/1_13.sql rename to internal/dbmodel/sql/postgres/013_add_roles.up.sql index 4299e82e8..3214c4dcf 100644 --- a/internal/dbmodel/sql/postgres/1_13.sql +++ b/internal/dbmodel/sql/postgres/013_add_roles.up.sql @@ -1,4 +1,5 @@ --- 1_13.sql is a migration that introduces the concept of roles to JIMM. +-- introduces the concept of roles to JIMM. + CREATE TABLE IF NOT EXISTS roles ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMP WITH TIME ZONE, @@ -6,5 +7,3 @@ CREATE TABLE IF NOT EXISTS roles ( name TEXT NOT NULL UNIQUE, uuid TEXT NOT NULL UNIQUE ); - -UPDATE versions SET major=1, minor=13 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_14.sql b/internal/dbmodel/sql/postgres/014_simplify_app_offers.up.sql similarity index 89% rename from internal/dbmodel/sql/postgres/1_14.sql rename to internal/dbmodel/sql/postgres/014_simplify_app_offers.up.sql index b1d9a3dd0..00ac2a9b7 100644 --- a/internal/dbmodel/sql/postgres/1_14.sql +++ b/internal/dbmodel/sql/postgres/014_simplify_app_offers.up.sql @@ -1,4 +1,5 @@ --- 1_14.sql is a migration simplifies application offers +-- simplifies application offers + DROP INDEX IF EXISTS idx_application_offer_connections_deleted_at; DROP INDEX IF EXISTS idx_application_offer_remote_endpoints_deleted_at; DROP INDEX IF EXISTS idx_application_offer_remote_spaces_deleted_at; @@ -14,6 +15,3 @@ ALTER TABLE application_offers DROP COLUMN IF EXISTS application_name; ALTER TABLE application_offers DROP COLUMN IF EXISTS application_description; ALTER TABLE application_offers DROP COLUMN IF EXISTS bindings; ALTER TABLE application_offers DROP COLUMN IF EXISTS charm_url; - -UPDATE versions SET major=1, minor=14 WHERE component='jimmdb'; - diff --git a/internal/dbmodel/sql/postgres/015_drop_controller_configs.up.sql b/internal/dbmodel/sql/postgres/015_drop_controller_configs.up.sql new file mode 100644 index 000000000..bfbc29b42 --- /dev/null +++ b/internal/dbmodel/sql/postgres/015_drop_controller_configs.up.sql @@ -0,0 +1,3 @@ +-- delete controller configs table + +DROP TABLE controller_configs; diff --git a/internal/dbmodel/sql/postgres/016_drop_identity_model_defaults.up.sql b/internal/dbmodel/sql/postgres/016_drop_identity_model_defaults.up.sql new file mode 100644 index 000000000..ee4351636 --- /dev/null +++ b/internal/dbmodel/sql/postgres/016_drop_identity_model_defaults.up.sql @@ -0,0 +1,3 @@ +-- delete identitymodel defaults table + +DROP TABLE identity_model_defaults; diff --git a/internal/dbmodel/sql/postgres/1_17.sql b/internal/dbmodel/sql/postgres/017_simplify_model_table.up.sql similarity index 76% rename from internal/dbmodel/sql/postgres/1_17.sql rename to internal/dbmodel/sql/postgres/017_simplify_model_table.up.sql index e0adc1eeb..2c2a13439 100644 --- a/internal/dbmodel/sql/postgres/1_17.sql +++ b/internal/dbmodel/sql/postgres/017_simplify_model_table.up.sql @@ -1,6 +1,5 @@ --- 1_17.sql remove non essential fields from model. +-- remove non essential fields from model. + ALTER TABLE models DROP COLUMN default_series, DROP COLUMN migration_controller_id, DROP COLUMN is_controller, DROP COLUMN cores, DROP COLUMN machines, DROP COLUMN units, DROP COLUMN type, DROP COLUMN status_status, DROP COLUMN status_info, DROP COLUMN status_data, DROP COLUMN status_since, DROP COLUMN status_version, DROP COLUMN sla_level, DROP COLUMN sla_owner; - -UPDATE versions SET major=1, minor=17 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/018_drop_versions_table.up.sql b/internal/dbmodel/sql/postgres/018_drop_versions_table.up.sql new file mode 100644 index 000000000..1c701610d --- /dev/null +++ b/internal/dbmodel/sql/postgres/018_drop_versions_table.up.sql @@ -0,0 +1,3 @@ +-- deletes the versions table + +DROP TABLE IF EXISTS versions; diff --git a/internal/dbmodel/sql/postgres/1_11.sql b/internal/dbmodel/sql/postgres/1_11.sql deleted file mode 100644 index a60d59efe..000000000 --- a/internal/dbmodel/sql/postgres/1_11.sql +++ /dev/null @@ -1,4 +0,0 @@ --- 1_11.sql is a migration that enforces uniqueness on URLs in application offers. -ALTER TABLE application_offers ADD UNIQUE (url); - -UPDATE versions SET major=1, minor=11 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_12.sql b/internal/dbmodel/sql/postgres/1_12.sql deleted file mode 100644 index 2463d9a98..000000000 --- a/internal/dbmodel/sql/postgres/1_12.sql +++ /dev/null @@ -1,6 +0,0 @@ --- 1_12.sql is a migration that deletes soft-deleted groups and --- drops the deleted_at column from the groups table. -DELETE FROM groups WHERE deleted_at IS NOT null; -ALTER TABLE groups DROP COLUMN deleted_at; - -UPDATE versions SET major=1, minor=12 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_15.sql b/internal/dbmodel/sql/postgres/1_15.sql deleted file mode 100644 index 40b991f9a..000000000 --- a/internal/dbmodel/sql/postgres/1_15.sql +++ /dev/null @@ -1,5 +0,0 @@ --- 1_15.sql is a migration to delete controller configs -DROP TABLE controller_configs; - -UPDATE versions SET major=1, minor=15 WHERE component='jimmdb'; - diff --git a/internal/dbmodel/sql/postgres/1_16.sql b/internal/dbmodel/sql/postgres/1_16.sql deleted file mode 100644 index 20ca59c10..000000000 --- a/internal/dbmodel/sql/postgres/1_16.sql +++ /dev/null @@ -1,5 +0,0 @@ --- 1_16.sql is a migration to delete identitymodel defaults -DROP TABLE identity_model_defaults; - -UPDATE versions SET major=1, minor=16 WHERE component='jimmdb'; - diff --git a/internal/dbmodel/sql/postgres/1_5.sql b/internal/dbmodel/sql/postgres/1_5.sql deleted file mode 100644 index 158f7265f..000000000 --- a/internal/dbmodel/sql/postgres/1_5.sql +++ /dev/null @@ -1,5 +0,0 @@ --- 1_5.sql is a migration that removes adds a column necessary for model migrations - -ALTER TABLE models ADD COLUMN migration_controller_id INTEGER REFERENCES controllers (id); - -UPDATE versions SET major=1, minor=5 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_7.sql b/internal/dbmodel/sql/postgres/1_7.sql deleted file mode 100644 index bc74e93b5..000000000 --- a/internal/dbmodel/sql/postgres/1_7.sql +++ /dev/null @@ -1,4 +0,0 @@ --- 1_7.sql is a migration that adds a UUID column to the identity table. -ALTER TABLE groups ADD COLUMN uuid TEXT NOT NULL UNIQUE; - -UPDATE versions SET major=1, minor=7 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_8.sql b/internal/dbmodel/sql/postgres/1_8.sql deleted file mode 100644 index d27afcb3d..000000000 --- a/internal/dbmodel/sql/postgres/1_8.sql +++ /dev/null @@ -1,4 +0,0 @@ --- 1_8.sql is a migration that adds a tls_hostname column to the controller table. -ALTER TABLE controllers ADD COLUMN tls_hostname TEXT; - -UPDATE versions SET major=1, minor=8 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/1_9.sql b/internal/dbmodel/sql/postgres/1_9.sql deleted file mode 100644 index d43ad6591..000000000 --- a/internal/dbmodel/sql/postgres/1_9.sql +++ /dev/null @@ -1,6 +0,0 @@ --- 1_9.sql is a migration that deletes soft-deleted controllers and --- drops the deleted_at column from the controllers table. -DELETE FROM controllers WHERE deleted_at IS NOT null; -ALTER TABLE controllers DROP COLUMN deleted_at; - -UPDATE versions SET major=1, minor=9 WHERE component='jimmdb'; diff --git a/internal/dbmodel/sql/postgres/versions.sql b/internal/dbmodel/sql/postgres/versions.sql deleted file mode 100644 index 43f17b3fc..000000000 --- a/internal/dbmodel/sql/postgres/versions.sql +++ /dev/null @@ -1,9 +0,0 @@ --- v.sql initialises the versions table --- This will be run unconditionally at application startup, so must be --- idempotent. - -CREATE TABLE IF NOT EXISTS versions ( - component TEXT NOT NULL PRIMARY KEY, - major INTEGER NOT NULL, - minor INTEGER NOT NULL -); diff --git a/internal/dbmodel/version.go b/internal/dbmodel/version.go deleted file mode 100644 index 72c39e0e4..000000000 --- a/internal/dbmodel/version.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2024 Canonical. - -// Package dbmodel contains the model objects for the relational storage -// database. -package dbmodel - -const ( - // Component is the component name in the version table for th - Component = "jimmdb" - - // Major is the major version of the model described in the dbmodel - // package. It should be incremented if the database model is modified - // in a way that is not backwards-compatible. That is, a column or - // table is added or changed in such a way that the default behaviour - // that would occur with a previous version of the package would break - // the data model. If this is incremented the Minor version should be - // reset to 0. - Major = 1 - - // Minor is the minor version of the model described in the dbmodel - // package. It should be incremented for any change made to the - // database model from database model in a released JIMM. - Minor = 17 -) - -type Version struct { - // Component represents the component that the stored version number - // is for. Currently there is only one known component "jimmdb" it - // mostly exists for the purposes of there being a primary key on the - // database table. - Component string `gorm:"primaryKey"` - - // Major is the stored major version. - Major int - - // Minor is the stored minor version. - Minor int -} diff --git a/internal/dbmodel/version_test.go b/internal/dbmodel/version_test.go deleted file mode 100644 index 5552c52f6..000000000 --- a/internal/dbmodel/version_test.go +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2024 Canonical. - -package dbmodel_test - -import ( - "testing" - - qt "github.com/frankban/quicktest" - - "github.com/canonical/jimm/v3/internal/dbmodel" -) - -func TestVersion(t *testing.T) { - c := qt.New(t) - db := gormDB(c) - - var v0 dbmodel.Version - result := db.First(&v0, "component = ?", dbmodel.Component) - c.Check(result.Error, qt.IsNil) - c.Check(v0.Major, qt.DeepEquals, dbmodel.Major) - c.Check(v0.Minor, qt.Equals, dbmodel.Minor) - - v1 := dbmodel.Version{ - Component: dbmodel.Component, - Major: dbmodel.Major, - Minor: dbmodel.Minor, - } - result = db.First(&v1, "component = ?", dbmodel.Component) - c.Assert(result.Error, qt.IsNil) - c.Check(v1, qt.DeepEquals, v1) - - v3 := dbmodel.Version{ - Component: dbmodel.Component, - Major: v1.Major + 1, - Minor: v1.Minor + 1, - } - result = db.Create(&v3) - c.Check(result.Error, qt.ErrorMatches, `.*violates unique constraint "versions_pkey".*`) - result = db.Save(&v3) - c.Assert(result.Error, qt.IsNil) - - var v4 dbmodel.Version - result = db.First(&v4, "component = ?", dbmodel.Component) - c.Assert(result.Error, qt.IsNil) - c.Check(v4, qt.DeepEquals, v3) -} diff --git a/internal/jimm/applicationoffer_test.go b/internal/jimm/applicationoffer_test.go index a668e109c..0f3f32e10 100644 --- a/internal/jimm/applicationoffer_test.go +++ b/internal/jimm/applicationoffer_test.go @@ -525,7 +525,7 @@ func TestGetApplicationOfferConsumeDetails(t *testing.T) { db := &db.Database{ DB: jimmtest.PostgresDB(c, func() time.Time { return now }), } - err = db.Migrate(ctx, false) + err = db.Migrate(ctx) c.Assert(err, qt.IsNil) u, err := dbmodel.NewIdentity("alice@canonical.com") diff --git a/internal/jimm/audit_log_test.go b/internal/jimm/audit_log_test.go index b1bd08083..7983cb6f3 100644 --- a/internal/jimm/audit_log_test.go +++ b/internal/jimm/audit_log_test.go @@ -31,7 +31,7 @@ func TestAuditLogCleanupServicePurgesLogs(t *testing.T) { }) c.Check(errors.ErrorCode(err), qt.Equals, errors.CodeUpgradeInProgress) - err = db.Migrate(context.Background(), true) + err = db.Migrate(context.Background()) c.Assert(err, qt.IsNil) // A log from 1 day ago diff --git a/internal/jimm/group/group_test.go b/internal/jimm/group/group_test.go index a74b0bbb7..6e82b09ce 100644 --- a/internal/jimm/group/group_test.go +++ b/internal/jimm/group/group_test.go @@ -34,7 +34,7 @@ func (s *groupManagerSuite) Init(c *qt.C) { db := &db.Database{ DB: jimmtest.PostgresDB(c, time.Now), } - err := db.Migrate(context.Background(), false) + err := db.Migrate(context.Background()) c.Assert(err, qt.IsNil) s.db = db diff --git a/internal/jimm/jimm.go b/internal/jimm/jimm.go index 961c02ee4..3f4e36a0c 100644 --- a/internal/jimm/jimm.go +++ b/internal/jimm/jimm.go @@ -231,7 +231,7 @@ func New(p Parameters) (*JIMM, error) { Parameters: p, } - if err := j.Database.Migrate(context.Background(), false); err != nil { + if err := j.Database.Migrate(context.Background()); err != nil { return nil, errors.E(err) } diff --git a/internal/jimm/jimm_test.go b/internal/jimm/jimm_test.go index 7885bc7da..ec0dd3bce 100644 --- a/internal/jimm/jimm_test.go +++ b/internal/jimm/jimm_test.go @@ -715,7 +715,7 @@ func TestFillMigrationTarget(t *testing.T) { db := &db.Database{ DB: jimmtest.PostgresDB(c, func() time.Time { return now }), } - err := db.Migrate(ctx, false) + err := db.Migrate(ctx) c.Assert(err, qt.IsNil) store := jimmtest.NewInMemoryCredentialStore() diff --git a/internal/jimm/model_cleanup_test.go b/internal/jimm/model_cleanup_test.go index 9e8354ffd..88675e792 100644 --- a/internal/jimm/model_cleanup_test.go +++ b/internal/jimm/model_cleanup_test.go @@ -93,7 +93,7 @@ func (s *modelCleanupSuite) Init(c *qt.C) { s.ofgaClient, _, _, err = jimmtest.SetupTestOFGAClient(c.Name()) c.Assert(err, qt.IsNil) s.jimm = jimmtest.NewJIMM(c, nil) - err = s.jimm.Database.Migrate(ctx, false) + err = s.jimm.Database.Migrate(ctx) c.Assert(err, qt.IsNil) s.jimmAdmin, err = s.jimm.GetUser(ctx, "alice@canonical.com") c.Assert(err, qt.IsNil) diff --git a/internal/jimm/model_test.go b/internal/jimm/model_test.go index 8a3bb835d..f6a27ed46 100644 --- a/internal/jimm/model_test.go +++ b/internal/jimm/model_test.go @@ -1783,7 +1783,7 @@ func TestModelSummaries(t *testing.T) { j := jimmtest.NewJIMM(c, nil) - err := j.Database.Migrate(ctx, false) + err := j.Database.Migrate(ctx) c.Assert(err, qt.IsNil) env := jimmtest.ParseEnvironment(c, modelSummariesTestEnv) diff --git a/internal/jimm/role/role_test.go b/internal/jimm/role/role_test.go index a0cafea30..786c179b4 100644 --- a/internal/jimm/role/role_test.go +++ b/internal/jimm/role/role_test.go @@ -35,7 +35,7 @@ func (s *roleManagerSuite) Init(c *qt.C) { db := &db.Database{ DB: jimmtest.PostgresDB(c, time.Now), } - err := db.Migrate(context.Background(), false) + err := db.Migrate(context.Background()) c.Assert(err, qt.IsNil) s.db = db diff --git a/internal/jimm/watcher_test.go b/internal/jimm/watcher_test.go index 80e24af81..1f78fd1f5 100644 --- a/internal/jimm/watcher_test.go +++ b/internal/jimm/watcher_test.go @@ -187,7 +187,7 @@ func TestModelSummaryWatcher(t *testing.T) { } env := jimmtest.ParseEnvironment(c, testWatcherEnv) - err := w.Database.Migrate(ctx, false) + err := w.Database.Migrate(ctx) c.Assert(err, qt.IsNil) env.PopulateDB(c, w.Database) @@ -233,7 +233,7 @@ func TestWatcherSetsControllerUnavailable(t *testing.T) { ) env := jimmtest.ParseEnvironment(c, testWatcherEnv) - err := w.Database.Migrate(ctx, false) + err := w.Database.Migrate(ctx) c.Assert(err, qt.IsNil) env.PopulateDB(c, w.Database) @@ -297,7 +297,7 @@ func TestWatcherClearsControllerUnavailable(t *testing.T) { } env := jimmtest.ParseEnvironment(c, testWatcherEnv) - err := w.Database.Migrate(ctx, false) + err := w.Database.Migrate(ctx) c.Assert(err, qt.IsNil) env.PopulateDB(c, w.Database) diff --git a/internal/jimmhttp/auth_handler_test.go b/internal/jimmhttp/auth_handler_test.go index ca130fccf..3d741d214 100644 --- a/internal/jimmhttp/auth_handler_test.go +++ b/internal/jimmhttp/auth_handler_test.go @@ -27,7 +27,7 @@ func setupDbAndSessionStore(c *qt.C) (*db.Database, sessions.Store) { db := &db.Database{ DB: jimmtest.PostgresDB(c, time.Now), } - c.Assert(db.Migrate(context.Background(), false), qt.IsNil) + c.Assert(db.Migrate(context.Background()), qt.IsNil) sqlDb, err := db.DB.DB() c.Assert(err, qt.IsNil) diff --git a/internal/jujuapi/admin_test.go b/internal/jujuapi/admin_test.go index 692151a1b..2953fb619 100644 --- a/internal/jujuapi/admin_test.go +++ b/internal/jujuapi/admin_test.go @@ -190,7 +190,7 @@ func (s *adminSuite) TestDeviceLogin(c *gc.C) { }, "test") defer conn.Close() - err := s.JIMM.Database.Migrate(context.Background(), false) + err := s.JIMM.Database.Migrate(context.Background()) c.Assert(err, gc.IsNil) // Create a user in keycloak diff --git a/internal/jujuapi/service_account_test.go b/internal/jujuapi/service_account_test.go index c4abe846b..4422fdb4c 100644 --- a/internal/jujuapi/service_account_test.go +++ b/internal/jujuapi/service_account_test.go @@ -162,7 +162,7 @@ func TestCopyServiceAccountCredential(t *testing.T) { pgDb := db.Database{ DB: jimmtest.PostgresDB(c, nil), } - err = pgDb.Migrate(context.Background(), false) + err = pgDb.Migrate(context.Background()) c.Assert(err, qt.IsNil) clientIdWithDomain, err := jimmnames.EnsureValidServiceAccountId(test.args.ClientID) c.Assert(err, qt.IsNil) @@ -256,7 +256,7 @@ func TestGetServiceAccount(t *testing.T) { pgDb := db.Database{ DB: jimmtest.PostgresDB(c, nil), } - err = pgDb.Migrate(context.Background(), false) + err = pgDb.Migrate(context.Background()) c.Assert(err, qt.IsNil) jimm := &jimmtest.JIMM{ UserLogin_: func(ctx context.Context, email string) (*openfga.User, error) { @@ -449,7 +449,7 @@ func TestUpdateServiceAccountCredentials(t *testing.T) { pgDb := db.Database{ DB: jimmtest.PostgresDB(c, nil), } - err = pgDb.Migrate(context.Background(), false) + err = pgDb.Migrate(context.Background()) c.Assert(err, qt.IsNil) jimm := &jimmtest.JIMM{ UpdateCloudCredential_: test.updateCloudCredential, @@ -580,7 +580,7 @@ func TestListServiceAccountCredentials(t *testing.T) { pgDb := db.Database{ DB: jimmtest.PostgresDB(c, nil), } - err = pgDb.Migrate(context.Background(), false) + err = pgDb.Migrate(context.Background()) c.Assert(err, qt.IsNil) jimm := &jimmtest.JIMM{ GetCloudCredential_: test.getCloudCredential, @@ -699,7 +699,7 @@ func TestGrantServiceAccountAccess(t *testing.T) { pgDb := db.Database{ DB: jimmtest.PostgresDB(c, nil), } - err = pgDb.Migrate(context.Background(), false) + err = pgDb.Migrate(context.Background()) c.Assert(err, qt.IsNil) jimm := &jimmtest.JIMM{ UserLogin_: func(ctx context.Context, email string) (*openfga.User, error) { return nil, nil }, diff --git a/internal/logger/migration_logger.go b/internal/logger/migration_logger.go new file mode 100644 index 000000000..c942f0d40 --- /dev/null +++ b/internal/logger/migration_logger.go @@ -0,0 +1,30 @@ +// Copyright 2024 Canonical. + +package logger + +import ( + "fmt" + + "go.uber.org/zap" +) + +// MigrationLogger provides a logger for use with DB migrations. +type MigrationLogger struct { + Logger *zap.Logger + IsVerbose bool +} + +// Printf implements the Printf function of the migrate.Logger interface. +func (l MigrationLogger) Printf(format string, v ...interface{}) { + line := fmt.Sprintf(format, v...) + // Remove unneeded new lines since the zap logger adds them. + if line[len(line)-1] == '\n' { + line = line[:len(line)-1] + } + l.Logger.Info(line) +} + +// Verbose implements the Verbose function of the migrate.Logger interface. +func (l MigrationLogger) Verbose() bool { + return l.IsVerbose +} diff --git a/internal/testutils/jimmtest/gorm.go b/internal/testutils/jimmtest/gorm.go index ce3e7fc0b..f8a24cfd6 100644 --- a/internal/testutils/jimmtest/gorm.go +++ b/internal/testutils/jimmtest/gorm.go @@ -296,7 +296,7 @@ func createTemplateDatabase() (string, string, error) { database := db.Database{ DB: gdb, } - if err := database.Migrate(context.Background(), true); err != nil { + if err := database.Migrate(context.Background()); err != nil { return "", "", errors.E(err, "error applying migrations on template database") } sqlDB, err := gdb.DB() diff --git a/internal/testutils/jimmtest/suite.go b/internal/testutils/jimmtest/suite.go index 3c77c4460..af9990e87 100644 --- a/internal/testutils/jimmtest/suite.go +++ b/internal/testutils/jimmtest/suite.go @@ -98,7 +98,7 @@ func (s *JIMMSuite) SetUpTest(c *gc.C) { database := &db.Database{ DB: pgdb, } - err = database.Migrate(ctx, false) + err = database.Migrate(ctx) c.Assert(err, gc.Equals, nil) alice, err := dbmodel.NewIdentity("alice@canonical.com") diff --git a/local/seed_db/main.go b/local/seed_db/main.go index cebfe4fee..9bae2bdf1 100644 --- a/local/seed_db/main.go +++ b/local/seed_db/main.go @@ -37,7 +37,7 @@ func main() { DB: gdb, } - err = db.Migrate(ctx, false) + err = db.Migrate(ctx) if err != nil { fmt.Println("failed to migrate to db ", err) os.Exit(1) diff --git a/rocks/jimm.yaml b/rocks/jimm.yaml index 7152600de..1d09998e0 100644 --- a/rocks/jimm.yaml +++ b/rocks/jimm.yaml @@ -35,10 +35,6 @@ parts: make build/server cp ./jimmsrv $CRAFT_PART_INSTALL/usr/local/bin - # The location of SQL files isn't configurable right now, as such we just - # place it in bin - cp -r ./internal/dbmodel/sql $CRAFT_PART_INSTALL/usr/local/bin/sql - # Convert the OpenFGA auth model to JSON and place a copy in the ROCK # Used by the charm to apply to the OpenFGA server, not by the container itself mkdir -p $CRAFT_PART_INSTALL/root/openfga/