diff --git a/README.md b/README.md index a9daaa0a..b590a71b 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,23 @@ make init ## Example Usage +### Health check endpoints + +The inventory API includes health check endpoints for readiness and liveness probes. + +#### Readyz +The readyz endpoint checks if the service is ready to handle requests. +```bash +curl http://localhost:8081/api/inventory/v1/readyz +``` + +#### Livez +The livez endpoint checks if the service is alive and functioning correctly. +```bash +curl http://localhost:8081/api/inventory/v1/livez +``` + +### Add hosts to inventory To add hosts to the inventory, use the following `curl` command: ```bash diff --git a/cmd/serve/serve.go b/cmd/serve/serve.go index 3aab8473..a461ba22 100644 --- a/cmd/serve/serve.go +++ b/cmd/serve/serve.go @@ -7,8 +7,6 @@ import ( "os/signal" "syscall" - "github.com/project-kessel/inventory-api/internal/service/health" - "github.com/spf13/cobra" "gorm.io/gorm" @@ -27,18 +25,21 @@ import ( rel "github.com/project-kessel/inventory-api/api/kessel/inventory/v1beta1/relationships" pb "github.com/project-kessel/inventory-api/api/kessel/inventory/v1beta1/resources" + healthrepo "github.com/project-kessel/inventory-api/internal/data/health" hostsrepo "github.com/project-kessel/inventory-api/internal/data/hosts" k8sclustersrepo "github.com/project-kessel/inventory-api/internal/data/k8sclusters" k8spoliciesrepo "github.com/project-kessel/inventory-api/internal/data/k8spolicies" notifsrepo "github.com/project-kessel/inventory-api/internal/data/notificationsintegrations" relationshipsrepo "github.com/project-kessel/inventory-api/internal/data/relationships" + healthctl "github.com/project-kessel/inventory-api/internal/biz/health" hostsctl "github.com/project-kessel/inventory-api/internal/biz/hosts" k8sclustersctl "github.com/project-kessel/inventory-api/internal/biz/k8sclusters" k8spoliciesctl "github.com/project-kessel/inventory-api/internal/biz/k8spolicies" notifsctl "github.com/project-kessel/inventory-api/internal/biz/notificationsintegrations" relationshipsctl "github.com/project-kessel/inventory-api/internal/biz/relationships" + healthssvc "github.com/project-kessel/inventory-api/internal/service/health" hostssvc "github.com/project-kessel/inventory-api/internal/service/hosts" k8sclusterssvc "github.com/project-kessel/inventory-api/internal/service/k8sclusters" k8spoliciessvc "github.com/project-kessel/inventory-api/internal/service/k8spolicies" @@ -184,7 +185,9 @@ func NewCommand( rel.RegisterKesselK8SPolicyIsPropagatedToK8SClusterServiceServer(server.GrpcServer, relationships_service) rel.RegisterKesselK8SPolicyIsPropagatedToK8SClusterServiceHTTPServer(server.HttpServer, relationships_service) - health_service := health.NewHealthService() + health_repo := healthrepo.New(db, authorizer, authzConfig) + health_controller := healthctl.New(health_repo, log.With(logger, "subsystem", "health_controller")) + health_service := healthssvc.New(health_controller) hb.RegisterKesselInventoryHealthServiceServer(server.GrpcServer, health_service) hb.RegisterKesselInventoryHealthServiceHTTPServer(server.HttpServer, health_service) diff --git a/go.mod b/go.mod index 21f0fe43..860378b7 100644 --- a/go.mod +++ b/go.mod @@ -14,18 +14,18 @@ require ( github.com/golang-jwt/jwt/v5 v5.2.1 github.com/google/wire v0.6.0 github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/project-kessel/relations-api v0.0.0-20240801131134-0f51350f3c3d + github.com/project-kessel/relations-api v0.0.0-20240912181134-54bbd73bdde7 github.com/prometheus/client_golang v1.20.3 github.com/spf13/cobra v1.8.1 github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 - go.opentelemetry.io/otel v1.29.0 - go.opentelemetry.io/otel/exporters/prometheus v0.51.0 - go.opentelemetry.io/otel/metric v1.29.0 - go.opentelemetry.io/otel/sdk v1.29.0 - go.opentelemetry.io/otel/sdk/metric v1.29.0 - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 + go.opentelemetry.io/otel v1.30.0 + go.opentelemetry.io/otel/exporters/prometheus v0.52.0 + go.opentelemetry.io/otel/metric v1.30.0 + go.opentelemetry.io/otel/sdk v1.30.0 + go.opentelemetry.io/otel/sdk/metric v1.30.0 + google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 google.golang.org/grpc v1.66.2 google.golang.org/protobuf v1.34.2 gopkg.in/yaml.v3 v3.0.1 @@ -42,7 +42,6 @@ require ( github.com/containerd/platforms v0.2.1 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/docker/docker v27.2.0+incompatible // indirect - github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/go-jose/go-jose/v4 v4.0.2 // indirect github.com/go-kratos/aegis v0.2.0 // indirect @@ -73,7 +72,7 @@ require ( github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/common v0.59.1 // indirect github.com/prometheus/procfs v0.15.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect @@ -83,17 +82,17 @@ require ( github.com/stoewer/go-strcase v1.3.0 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/subosito/gotenv v1.6.0 // indirect - go.opentelemetry.io/otel/trace v1.29.0 // indirect + go.opentelemetry.io/otel/trace v1.30.0 // indirect go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.25.0 // indirect + golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/oauth2 v0.21.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.24.0 // indirect - golang.org/x/text v0.16.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect + golang.org/x/net v0.29.0 // indirect + golang.org/x/oauth2 v0.22.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.25.0 // indirect + golang.org/x/text v0.18.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/go.sum b/go.sum index b7530ba4..81d45e10 100644 --- a/go.sum +++ b/go.sum @@ -214,8 +214,8 @@ github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWm github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -348,15 +348,15 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig= github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/project-kessel/relations-api v0.0.0-20240801131134-0f51350f3c3d h1:c/WNCPLwnrgals2FILxNmKvGOKAo/sIL7VuZHQA1Zlk= -github.com/project-kessel/relations-api v0.0.0-20240801131134-0f51350f3c3d/go.mod h1:/BaL63PtSHbygpHf2lN/aXET9XCMlg/Rx0v02E/gwUU= +github.com/project-kessel/relations-api v0.0.0-20240912181134-54bbd73bdde7 h1:8Jn9Tkz2zP5gMhzBWCRa49Od8VBqJCFBapaAY0fTVUU= +github.com/project-kessel/relations-api v0.0.0-20240912181134-54bbd73bdde7/go.mod h1:KbgiAPnLEqlEbRda41lGTX7+ojnMlqg+B2DeqDCgjFo= github.com/prometheus/client_golang v1.20.3 h1:oPksm4K8B+Vt35tUhw6GbSNSgVlVSBH0qELP/7u83l4= github.com/prometheus/client_golang v1.20.3/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/common v0.59.1 h1:LXb1quJHWm1P6wq/U824uxYi4Sg0oGvNeUm1z5dJoX0= +github.com/prometheus/common v0.59.1/go.mod h1:GpWM7dewqmVYcd7SmRaiWVe9SSqjf0UrwnYnpEZNuT0= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc h1:zAsgcP8MhzAbhMnB1QQ2O7ZhWYVGYSR2iVcjzQuPV+o= @@ -455,8 +455,8 @@ go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0. go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1/go.mod h1:GnOaBaFQ2we3b9AGWJpsBa7v1S5RlQzlC3O7dRMxZhM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -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 v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts= +go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= @@ -469,16 +469,16 @@ go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqhe go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= -go.opentelemetry.io/otel/exporters/prometheus v0.51.0 h1:G7uexXb/K3T+T9fNLCCKncweEtNEBMTO+46hKX5EdKw= -go.opentelemetry.io/otel/exporters/prometheus v0.51.0/go.mod h1:v0mFe5Kk7woIh938mrZBJBmENYquyA0IICrlYm4Y0t4= -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/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= -go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= -go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= -go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= -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.opentelemetry.io/otel/exporters/prometheus v0.52.0 h1:kmU3H0b9ufFSi8IQCcxack+sWUblKkFbqWYs6YiACGQ= +go.opentelemetry.io/otel/exporters/prometheus v0.52.0/go.mod h1:+wsAp2+JhuGXX7YRkjlkx6hyWY3ogFPfNA4x3nyiAh0= +go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w= +go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ= +go.opentelemetry.io/otel/sdk v1.30.0 h1:cHdik6irO49R5IysVhdn8oaiR9m8XluDaJAs4DfOrYE= +go.opentelemetry.io/otel/sdk v1.30.0/go.mod h1:p14X4Ok8S+sygzblytT1nqG98QG2KYKv++HE0LY/mhg= +go.opentelemetry.io/otel/sdk/metric v1.30.0 h1:QJLT8Pe11jyHBHfSAgYH7kEmT24eX792jZO1bo4BXkM= +go.opentelemetry.io/otel/sdk/metric v1.30.0/go.mod h1:waS6P3YqFNzeP01kuo/MBBYqaoBJl7efRQHOaydhy1Y= +go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc= +go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o= go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -501,8 +501,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw= golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ= @@ -532,11 +532,11 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= +golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.22.0 h1:BzDx2FehcG7jJwgWLELCdmLuxk2i+x9UDpSiss2u0ZA= +golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -547,8 +547,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -565,16 +565,16 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= -golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -582,8 +582,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= +golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -611,10 +611,10 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa h1:ePqxpG3LVx+feAUOx8YmR5T7rc0rdzK8DyxM8cQ9zq0= google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:CnZenrTdRJb7jc+jOm0Rkywq+9wh0QC4U8tyiRbEPPM= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc= +google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/internal/authz/allow/allow.go b/internal/authz/allow/allow.go index fc74901c..625e4e0d 100644 --- a/internal/authz/allow/allow.go +++ b/internal/authz/allow/allow.go @@ -2,6 +2,7 @@ package allow import ( "context" + kesselv1 "github.com/project-kessel/relations-api/api/kessel/relations/v1" "github.com/go-kratos/kratos/v2/log" kessel "github.com/project-kessel/relations-api/api/kessel/relations/v1beta1" @@ -18,6 +19,11 @@ func New(logger *log.Helper) *AllowAllAuthz { } } +func (a *AllowAllAuthz) Health(ctx context.Context) (*kesselv1.GetReadyzResponse, error) { + return &kesselv1.GetReadyzResponse{Status: "OK", Code: 200}, nil + +} + func (a *AllowAllAuthz) Check(ctx context.Context, r *kessel.CheckRequest) (*kessel.CheckResponse, error) { return &kessel.CheckResponse{ Allowed: kessel.CheckResponse_ALLOWED_TRUE, diff --git a/internal/authz/api/authz-service.go b/internal/authz/api/authz-service.go index 3d3157f2..6e00f9d6 100644 --- a/internal/authz/api/authz-service.go +++ b/internal/authz/api/authz-service.go @@ -2,11 +2,12 @@ package api import ( "context" - + kesselv1 "github.com/project-kessel/relations-api/api/kessel/relations/v1" kessel "github.com/project-kessel/relations-api/api/kessel/relations/v1beta1" ) type Authorizer interface { + Health(ctx context.Context) (*kesselv1.GetReadyzResponse, error) Check(context.Context, *kessel.CheckRequest) (*kessel.CheckResponse, error) CreateTuples(context.Context, *kessel.CreateTuplesRequest) (*kessel.CreateTuplesResponse, error) DeleteTuples(context.Context, *kessel.DeleteTuplesRequest) (*kessel.DeleteTuplesResponse, error) diff --git a/internal/authz/authz.go b/internal/authz/authz.go index 4555c562..c85fd65d 100644 --- a/internal/authz/authz.go +++ b/internal/authz/authz.go @@ -21,3 +21,16 @@ func New(ctx context.Context, config CompletedConfig, logger *log.Helper) (api.A return nil, fmt.Errorf("Unrecognized authz.impl: %s", config.Authz) } } + +func CheckAuthorizer(config CompletedConfig) string { + var authType string + switch config.Authz { + case AllowAll: + authType = "AllowAll" + case Kessel: + authType = "Kessel" + default: + authType = "Unknown" + } + return authType +} diff --git a/internal/authz/kessel/kessel.go b/internal/authz/kessel/kessel.go index f04de57f..94fe7760 100644 --- a/internal/authz/kessel/kessel.go +++ b/internal/authz/kessel/kessel.go @@ -6,15 +6,26 @@ import ( "github.com/go-kratos/kratos/v2/log" authzapi "github.com/project-kessel/inventory-api/internal/authz/api" + kesselv1 "github.com/project-kessel/relations-api/api/kessel/relations/v1" kessel "github.com/project-kessel/relations-api/api/kessel/relations/v1beta1" "google.golang.org/grpc" ) type KesselAuthz struct { - CheckService kessel.KesselCheckServiceClient - TupleService kessel.KesselTupleServiceClient - tokenClient *tokenClient - Logger *log.Helper + HealthService kesselv1.KesselRelationsHealthServiceClient + CheckService kessel.KesselCheckServiceClient + TupleService kessel.KesselTupleServiceClient + tokenClient *tokenClient + Logger *log.Helper +} + +func (a *KesselAuthz) Health(ctx context.Context) (*kesselv1.GetReadyzResponse, error) { + opts, err := a.getCallOptions() + if err != nil { + return nil, err + } + log.Infof("Checking relations-api readyz endpoint") + return a.HealthService.GetReadyz(ctx, &kesselv1.GetReadyzRequest{}, opts...) } var _ authzapi.Authorizer = &KesselAuthz{} @@ -24,10 +35,11 @@ func New(ctx context.Context, config CompletedConfig, logger *log.Helper) (*Kess tokenCli := NewTokenClient(config.tokenConfig) return &KesselAuthz{ - CheckService: kessel.NewKesselCheckServiceClient(config.gRPCConn), - TupleService: kessel.NewKesselTupleServiceClient(config.gRPCConn), - Logger: logger, - tokenClient: tokenCli, + HealthService: kesselv1.NewKesselRelationsHealthServiceClient(config.gRPCConn), + CheckService: kessel.NewKesselCheckServiceClient(config.gRPCConn), + TupleService: kessel.NewKesselTupleServiceClient(config.gRPCConn), + Logger: logger, + tokenClient: tokenCli, }, nil } diff --git a/internal/biz/health/health.go b/internal/biz/health/health.go new file mode 100644 index 00000000..ac4dc7b4 --- /dev/null +++ b/internal/biz/health/health.go @@ -0,0 +1,26 @@ +package biz + +import ( + "context" + "github.com/go-kratos/kratos/v2/log" + pb "github.com/project-kessel/inventory-api/api/kessel/inventory/v1" +) + +type HealthRepo interface { + IsBackendAvailable(ctx context.Context) (*pb.GetReadyzResponse, error) +} + +// HealthUsecase is a Health usecase. +type HealthUsecase struct { + repo HealthRepo + log *log.Helper +} + +// New creates a new a Health usecase. +func New(repo HealthRepo, logger log.Logger) *HealthUsecase { + return &HealthUsecase{repo: repo, log: log.NewHelper(logger)} +} + +func (rc *HealthUsecase) IsBackendAvailable(ctx context.Context) (*pb.GetReadyzResponse, error) { + return rc.repo.IsBackendAvailable(ctx) +} diff --git a/internal/data/health/health.go b/internal/data/health/health.go new file mode 100644 index 00000000..c53f61ee --- /dev/null +++ b/internal/data/health/health.go @@ -0,0 +1,60 @@ +package health + +import ( + "context" + "github.com/go-kratos/kratos/v2/log" + pb "github.com/project-kessel/inventory-api/api/kessel/inventory/v1" + "github.com/project-kessel/inventory-api/internal/authz" + authzapi "github.com/project-kessel/inventory-api/internal/authz/api" + "gorm.io/gorm" +) + +type healthRepo struct { + DB *gorm.DB + Authz authzapi.Authorizer + CompletedAuth authz.CompletedConfig +} + +func New(g *gorm.DB, a authzapi.Authorizer, completedAuth authz.CompletedConfig) *healthRepo { + return &healthRepo{ + DB: g, + Authz: a, + CompletedAuth: completedAuth, + } +} + +func (r *healthRepo) IsBackendAvailable(ctx context.Context) (*pb.GetReadyzResponse, error) { + storageType := r.DB.Dialector.Name() + sqlDB, dbErr := r.DB.DB() + if dbErr == nil { + dbErr = sqlDB.PingContext(ctx) + } + health, apiErr := r.Authz.Health(ctx) + + if dbErr != nil && apiErr != nil { + log.Errorf("STORAGE UNHEALTHY: %s and RELATIONS-API UNHEALTHY", storageType) + return newResponse("STORAGE UNHEALTHY: "+storageType+" and RELATIONS-API UNHEALTHY", 500), nil + } + + if dbErr != nil { + log.Errorf("STORAGE UNHEALTHY: %s", storageType) + return newResponse("STORAGE UNHEALTHY: "+storageType, 500), nil + } + + if apiErr != nil { + log.Errorf("RELATIONS-API UNHEALTHY") + return newResponse("RELATIONS-API UNHEALTHY", 500), nil + } + if authz.CheckAuthorizer(r.CompletedAuth) == "Kessel" { + log.Infof("Storage type %s and relations-api %s", storageType, health.GetStatus()) + return newResponse("STORAGE "+storageType+" and RELATIONS-API", 200), nil + } + return newResponse("Storage type "+storageType, 200), nil +} + +func newResponse(status string, code int) *pb.GetReadyzResponse { + return &pb.GetReadyzResponse{ + Status: status, + Code: uint32(code), + } +} diff --git a/internal/service/health/health.go b/internal/service/health/health.go index 4b6b8e39..9033e6bd 100644 --- a/internal/service/health/health.go +++ b/internal/service/health/health.go @@ -2,22 +2,33 @@ package health import ( "context" - + "github.com/go-kratos/kratos/v2/log" pb "github.com/project-kessel/inventory-api/api/kessel/inventory/v1" + "github.com/project-kessel/inventory-api/internal/authz" + biz "github.com/project-kessel/inventory-api/internal/biz/health" ) type HealthService struct { pb.UnimplementedKesselInventoryHealthServiceServer + Ctl *biz.HealthUsecase + Config *authz.CompletedConfig } -func NewHealthService() *HealthService { - return &HealthService{} +func New(c *biz.HealthUsecase) *HealthService { + return &HealthService{ + Ctl: c, + } } func (s *HealthService) GetLivez(ctx context.Context, req *pb.GetLivezRequest) (*pb.GetLivezResponse, error) { - return &pb.GetLivezResponse{Status: "OK", Code: 200}, nil + log.Infof("Performing livez check") + return &pb.GetLivezResponse{ + Status: "OK", + Code: 200, + }, nil } func (s *HealthService) GetReadyz(ctx context.Context, req *pb.GetReadyzRequest) (*pb.GetReadyzResponse, error) { - return &pb.GetReadyzResponse{Status: "OK", Code: 200}, nil + + return s.Ctl.IsBackendAvailable(ctx) }