From 342e464f981e8c693a3ae19fc5f5c1d32039a186 Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Fri, 22 Sep 2023 21:15:45 +0000 Subject: [PATCH 01/10] remove old Signed-off-by: Matt Siwiec --- examples/01_ssh-service-one-pool/input.json | 45 --------------- examples/01_ssh-service-one-pool/result.cfg | 31 ----------- examples/02_ssh-service-two-pools/input.json | 58 -------------------- examples/02_ssh-service-two-pools/result.cfg | 33 ----------- examples/03_http-and-https/input.json | 53 ------------------ examples/03_http-and-https/result.cfg | 39 ------------- examples/blank.cfg | 22 -------- examples/datplaneapi.hcl | 33 ----------- 8 files changed, 314 deletions(-) delete mode 100644 examples/01_ssh-service-one-pool/input.json delete mode 100644 examples/01_ssh-service-one-pool/result.cfg delete mode 100644 examples/02_ssh-service-two-pools/input.json delete mode 100644 examples/02_ssh-service-two-pools/result.cfg delete mode 100644 examples/03_http-and-https/input.json delete mode 100644 examples/03_http-and-https/result.cfg delete mode 100644 examples/blank.cfg delete mode 100644 examples/datplaneapi.hcl diff --git a/examples/01_ssh-service-one-pool/input.json b/examples/01_ssh-service-one-pool/input.json deleted file mode 100644 index c67121929..000000000 --- a/examples/01_ssh-service-one-pool/input.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "lb_uuid": "58622a8d-54a2-4b0c-8b5f-8de7dff29f6f", - "lb_ip_address": "86.75.30.9", - "slug": "my-ssh-loadbalancer", - "assignments": [ - { - "uuid":"8a48a7a9-b17b-4ac0-89d5-6c2b7976e24f", - "frontend": - { - "uuid":"16dd23d7-d3ab-42c8-a645-3169f2659a0b", - "port": 22 - }, - "pools": [ - { - "uuid": "49faa4a3-8d0b-4a7a-8bb9-7ed1b5995e49", - "name": "ssh-service-a", - "origins": [ - { - "uuid": "c0a80101-0000-0000-0000-000000000001", - "name": "svr1-2222", - "address": "1.2.3.4", - "enabled": true, - "port": "2222" - }, - { - "uuid": "c0a80101-0000-0000-0000-000000000002", - "name": "svr1-222", - "address": "1.2.3.4", - "enabled": true, - "port": "222", - "weight": 2 - }, - { - "uuid":"c0a80101-0000-0000-0000-000000000003", - "name": "svr2", - "address": "4.3.2.1", - "enabled": false, - "port": "2222" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/examples/01_ssh-service-one-pool/result.cfg b/examples/01_ssh-service-one-pool/result.cfg deleted file mode 100644 index 5691e8b58..000000000 --- a/examples/01_ssh-service-one-pool/result.cfg +++ /dev/null @@ -1,31 +0,0 @@ -global - master-worker - chroot /usr/share/haproxy - user haproxy - maxconn 200 - pidfile /run/haproxy.pid - stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners - log 127.0.0.1 local0 - -defaults - log global - mode tcp - option tcplog - retries 3 - timeout connect 5s - timeout client 50s - timeout server 50s - -program dataplaneapi - command dataplaneapi -f dataplaneapi.hcl - no option start-on-reload - -backend 8a48a7a9-b17b-4ac0-89d5-6c2b7976e24f - server c0a80101-0000-0000-0000-000000000001 1.2.3.4:2222 check port 2222 - server c0a80101-0000-0000-0000-000000000002 1.2.3.4:222 check port 222 - server c0a80101-0000-0000-0000-000000000003 4.3.2.1:2222 check port 2222 disabled - -frontend 16dd23d7-d3ab-42c8-a645-3169f2659a0b - bind ipv4@:2222 - use_backend 8a48a7a9-b17b-4ac0-89d5-6c2b7976e24f - diff --git a/examples/02_ssh-service-two-pools/input.json b/examples/02_ssh-service-two-pools/input.json deleted file mode 100644 index a524c0f0e..000000000 --- a/examples/02_ssh-service-two-pools/input.json +++ /dev/null @@ -1,58 +0,0 @@ -{ - "lb_uuid": "58622a8d-54a2-4b0c-8b5f-8de7dff29f6f", - "lb_ip_address": "86.75.30.9", - "slug": "my-ssh-loadbalancer", - "assignments": [ - { - "uuid":"8a48a7a9-b17b-4ac0-89d5-6c2b7976e24f", - "frontend": - { - "uuid":"16dd23d7-d3ab-42c8-a645-3169f2659a0b", - "port": 22 - }, - "pools": [ - { - "uuid": "49faa4a3-8d0b-4a7a-8bb9-7ed1b5995e49", - "name": "ssh-service-a", - "origins": [ - { - "uuid": "c0a80101-0000-0000-0000-000000000001", - "name": "svr1-2222", - "address": "1.2.3.4", - "enabled": true, - "port": "2222" - }, - { - "uuid": "c0a80101-0000-0000-0000-000000000002", - "name": "svr1-222", - "address": "1.2.3.4", - "enabled": true, - "port": "222", - "weight": 2 - }, - { - "uuid":"c0a80101-0000-0000-0000-000000000003", - "name": "svr2", - "address": "4.3.2.1", - "enabled": false, - "port": "2222" - } - ] - }, - { - "uuid": "c9bd57ac-6d88-4786-849e-0b228c17d645", - "name": "ssh-service-b", - "origins": [ - { - "uuid": "b1982331-0000-0000-0000-000000000001", - "name": "svr1-2222", - "address": "7.8.9.0", - "enabled": true, - "port": "2222" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/examples/02_ssh-service-two-pools/result.cfg b/examples/02_ssh-service-two-pools/result.cfg deleted file mode 100644 index bafc0415b..000000000 --- a/examples/02_ssh-service-two-pools/result.cfg +++ /dev/null @@ -1,33 +0,0 @@ -global - master-worker - chroot /usr/share/haproxy - user haproxy - maxconn 200 - pidfile /run/haproxy.pid - stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners - log 127.0.0.1 local0 - -defaults - log global - mode tcp - option tcplog - retries 3 - timeout connect 5s - timeout client 50s - timeout server 50s - -program dataplaneapi - command dataplaneapi -f dataplaneapi.hcl - no option start-on-reload - -backend 8a48a7a9-b17b-4ac0-89d5-6c2b7976e24f - server c0a80101-0000-0000-0000-000000000001 1.2.3.4:2222 check port 2222 - server c0a80101-0000-0000-0000-000000000002 1.2.3.4:222 check port 222 - server c0a80101-0000-0000-0000-000000000003 4.3.2.1:2222 check port 2222 disabled - server b1982331-0000-0000-0000-000000000001 7.8.9.0:2222 check port 2222 - -frontend 16dd23d7-d3ab-42c8-a645-3169f2659a0b - mode tcp - bind ipv4@:2222 - use_backend 8a48a7a9-b17b-4ac0-89d5-6c2b7976e24f - diff --git a/examples/03_http-and-https/input.json b/examples/03_http-and-https/input.json deleted file mode 100644 index 3f346323e..000000000 --- a/examples/03_http-and-https/input.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "lb_uuid": "a522bc95-2a74-4005-919d-6ae0a5be056d", - "lb_ip_address": "86.75.30.9", - "slug": "my-app-loadbalancer", - "assignments": [ - { - "uuid":"3da05271-c64c-480c-8c1e-f37eceb66ef5", - "frontend": - { - "uuid":"16dd23d7-d3ab-42c8-a645-3169f2659a0b", - "port": 80 - }, - "pools": [ - { - "uuid": "49faa4a3-8d0b-4a7a-8bb9-7ed1b5995e49", - "name": "ssh-service-a", - "origins": [ - { - "uuid": "c0a80101-0000-0000-0000-000000000001", - "name": "svr1", - "address": "3.1.4.1", - "enabled": true, - "port": "80" - } - ] - } - ] - }, - { - "uuid":"c1a3be07-afd7-4a67-9c53-ade6d7c58bd9", - "frontend": - { - "uuid":"8ca812cc-9c3d-4fed-95be-40a773f7d876", - "port": 443 - }, - "pools": [ - { - "uuid": "d94ad98b-b074-4794-896f-d71ae3b7b0ac", - "name": "ssh-service-a", - "origins": [ - { - "uuid": "676a1536-0a17-4676-9296-ee957e5871c1", - "name": "svr1", - "address": "3.1.4.1", - "enabled": true, - "port": "443" - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/examples/03_http-and-https/result.cfg b/examples/03_http-and-https/result.cfg deleted file mode 100644 index 0a36263ac..000000000 --- a/examples/03_http-and-https/result.cfg +++ /dev/null @@ -1,39 +0,0 @@ -global - master-worker - chroot /usr/share/haproxy - user haproxy - maxconn 200 - pidfile /run/haproxy.pid - stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners - log 127.0.0.1 local0 - -defaults - log global - mode tcp - option tcplog - retries 3 - timeout connect 5s - timeout client 50s - timeout server 50s - -program dataplaneapi - command dataplaneapi -f dataplaneapi.hcl - no option start-on-reload - -backend 3da05271-c64c-480c-8c1e-f37eceb66ef5 - mode tcp - server c0a80101-0000-0000-0000-000000000001 3.1.4.1:80 check port 80 - -frontend 16dd23d7-d3ab-42c8-a645-3169f2659a0b - mode tcp - bind ipv4@:80 - use_backend 3da05271-c64c-480c-8c1e-f37eceb66ef5 - -backend c1a3be07-afd7-4a67-9c53-ade6d7c58bd9 - mode tcp - server 676a1536-0a17-4676-9296-ee957e5871c1 3.1.4.1:443 check port 443 - -frontend 8ca812cc-9c3d-4fed-95be-40a773f7d876 - mode tcp - bind ipv4@:443 - use_backend c1a3be07-afd7-4a67-9c53-ade6d7c58bd9 diff --git a/examples/blank.cfg b/examples/blank.cfg deleted file mode 100644 index d715081fb..000000000 --- a/examples/blank.cfg +++ /dev/null @@ -1,22 +0,0 @@ -global - master-worker - chroot /usr/share/haproxy - user haproxy - maxconn 200 - pidfile /run/haproxy.pid - stats socket /var/run/haproxy.sock mode 660 level admin expose-fd listeners - log 127.0.0.1 local0 - -defaults - log global - mode tcp - option tcplog - retries 3 - timeout connect 5s - timeout client 50s - timeout server 50s - - -program dataplaneapi - command dataplaneapi -f dataplaneapi.hcl - no option start-on-reload diff --git a/examples/datplaneapi.hcl b/examples/datplaneapi.hcl deleted file mode 100644 index bbd267ee1..000000000 --- a/examples/datplaneapi.hcl +++ /dev/null @@ -1,33 +0,0 @@ -config_version = 2 - -name = "$podname" - -mode = "single" - -dataplaneapi { - host = "127.0.0.1" - port = 5555 - - user "admin" { - insecure = true - password = "adminpwd" - } - - transaction { - transaction_dir = "/tmp/haproxy" - } - - advertised {} -} - -haproxy { - config_file = "/etc/haproxy/haproxy.cfg" - haproxy_bin = "haproxy" - - reload { - reload_delay = 15 - reload_cmd = "kill SIGUSR 1" - restart_cmd = "systemctl restart haproxy" - reload_strategy = "custom" - } -} \ No newline at end of file From f470b33bc0f727e793b1af5d792089e232c78595 Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Fri, 22 Sep 2023 21:17:33 +0000 Subject: [PATCH 02/10] loadbalancer error logs, do no expose internals Signed-off-by: Matt Siwiec --- go.mod | 55 +++++----- go.sum | 115 ++++++++++---------- internal/graphapi/errors.go | 13 ++- internal/graphapi/loadbalancer.resolvers.go | 86 ++++++++++----- internal/graphapi/loadbalancer_test.go | 14 ++- 5 files changed, 162 insertions(+), 121 deletions(-) diff --git a/go.mod b/go.mod index 0e254d890..7b6b154a7 100644 --- a/go.mod +++ b/go.mod @@ -23,10 +23,10 @@ require ( github.com/testcontainers/testcontainers-go/modules/postgres v0.23.0 github.com/vektah/gqlparser/v2 v2.5.8 github.com/wundergraph/graphql-go-tools v1.62.3 - go.infratographer.com/permissions-api v0.2.5 + go.infratographer.com/permissions-api v0.2.6 go.infratographer.com/x v0.3.8 - go.uber.org/zap v1.25.0 - golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 + go.uber.org/zap v1.26.0 + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 ) require ( @@ -65,7 +65,7 @@ require ( github.com/google/go-cmp v0.5.9 // indirect github.com/google/uuid v1.3.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.3 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -97,13 +97,13 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/nats-io/jwt/v2 v2.4.1 // indirect github.com/nats-io/nats-server/v2 v2.9.17 // indirect - github.com/nats-io/nats.go v1.28.0 // indirect + github.com/nats-io/nats.go v1.29.0 // indirect github.com/nats-io/nkeys v0.4.4 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc4 // indirect github.com/opencontainers/runc v1.1.7 // indirect - github.com/pelletier/go-toml/v2 v2.0.9 // indirect + github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pressly/goose/v3 v3.15.0 // indirect @@ -123,34 +123,33 @@ require ( github.com/vmihailenco/msgpack/v5 v5.0.0-beta.9 // indirect github.com/vmihailenco/tagparser v0.1.2 // indirect github.com/zclconf/go-cty v1.8.0 // indirect - go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.42.0 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect - go.opentelemetry.io/otel v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/jaeger v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 // indirect - go.opentelemetry.io/otel/metric v1.16.0 // indirect - go.opentelemetry.io/otel/sdk v1.16.0 // indirect - go.opentelemetry.io/otel/trace v1.16.0 // indirect + go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect + go.opentelemetry.io/otel v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 // indirect + go.opentelemetry.io/otel/metric v1.18.0 // indirect + go.opentelemetry.io/otel/sdk v1.18.0 // indirect + go.opentelemetry.io/otel/trace v1.18.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.step.sm/crypto v0.35.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.12.0 // indirect + golang.org/x/crypto v0.13.0 // indirect golang.org/x/mod v0.12.0 // indirect - golang.org/x/net v0.14.0 // indirect - golang.org/x/oauth2 v0.10.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/net v0.15.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect + golang.org/x/tools v0.13.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20230815205213-6bfd019c3878 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20230815205213-6bfd019c3878 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 // indirect - google.golang.org/grpc v1.57.0 // indirect + google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb // indirect + google.golang.org/grpc v1.58.1 // indirect google.golang.org/protobuf v1.31.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect diff --git a/go.sum b/go.sum index eca15ae3b..0f651df29 100644 --- a/go.sum +++ b/go.sum @@ -74,7 +74,6 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6 github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q= github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/brianvoe/gofakeit/v6 v6.23.1 h1:k2gX0hQpJStvixDbbw8oJOvPBg0XmHJWbSOF5JkiUHw= @@ -246,8 +245,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/graph-gophers/graphql-go v1.5.0 h1:fDqblo50TEpD0LY7RXk/LFVYEVqo3+tXMNMPSVXA1yc= github.com/graph-gophers/graphql-transport-ws v0.0.2 h1:DbmSkbIGzj8SvHei6n8Mh9eLQin8PtA8xY9eCzjRpvo= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2 h1:dygLcbEBA+t/P7ck6a8AkXv6juQ4cK0RHBoh32jxhHM= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2/go.mod h1:Ap9RLCIJVtgQg1/BBgVEfypOAySvvlcpcVQkSzJCH4Y= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0 h1:RtRsiaGvWxcwd8y3BiRZxsylPT8hLWZ5SPcfI+3IDNk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.0/go.mod h1:TzP6duP4Py2pHLVPPQp42aoYI92+PCrVotyR5e8Vqlk= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -400,8 +399,8 @@ github.com/nats-io/jwt/v2 v2.4.1 h1:Y35W1dgbbz2SQUYDPCaclXcuqleVmpbRa7646Jf2EX4= github.com/nats-io/jwt/v2 v2.4.1/go.mod h1:24BeQtRwxRV8ruvC4CojXlx/WQ/VjuwlYiH+vu/+ibI= github.com/nats-io/nats-server/v2 v2.9.17 h1:gFpUQ3hqIDJrnqog+Bl5vaXg+RhhYEZIElasEuRn2tw= github.com/nats-io/nats-server/v2 v2.9.17/go.mod h1:eQysm3xDZmIjfkjr7DuD9DjRFpnxQc2vKVxtEg0Dp6s= -github.com/nats-io/nats.go v1.28.0 h1:Th4G6zdsz2d0OqXdfzKLClo6bOfoI/b1kInhRtFIy5c= -github.com/nats-io/nats.go v1.28.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= +github.com/nats-io/nats.go v1.29.0 h1:dSXZ+SZeGyTdHVYeXimeq12FsIpb9dM8CJ2IZFiHcyE= +github.com/nats-io/nats.go v1.29.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc= github.com/nats-io/nkeys v0.4.4 h1:xvBJ8d69TznjcQl9t6//Q5xXuVhyYiSos6RPtvQNTwA= github.com/nats-io/nkeys v0.4.4/go.mod h1:XUkxdLPTufzlihbamfzQ7mw/VGx6ObUs+0bN5sNvt64= github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= @@ -412,8 +411,8 @@ github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYB github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opencontainers/runc v1.1.7 h1:y2EZDS8sNng4Ksf0GUYNhKbTShZJPJg1FiXJNH/uoCk= github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh/smNYNOhA50= -github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0= -github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= +github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= +github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -514,8 +513,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA= github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.infratographer.com/permissions-api v0.2.5 h1:ZU5p+jGD2vVxok2MzhGLNuHGUZQ7qKtNJcMxRp3GMGg= -go.infratographer.com/permissions-api v0.2.5/go.mod h1:2uNlcC/gsWXhxPaQ+NP/Kwf02Wu3bCPQ3FF7vGgbnwU= +go.infratographer.com/permissions-api v0.2.6 h1:Xet3HF18SJHCoP5S3KTF7JAhD9RA1jGTa80QSII7ieY= +go.infratographer.com/permissions-api v0.2.6/go.mod h1:2uNlcC/gsWXhxPaQ+NP/Kwf02Wu3bCPQ3FF7vGgbnwU= go.infratographer.com/x v0.3.8 h1:ZKL/oeTO8an4p58ZXtDdCMl9DVr7Y+RAY2EVeTf1/Uc= go.infratographer.com/x v0.3.8/go.mod h1:H8O2vkWmo26WNuQEFS2PlJoms9YLJ7BNiwFNMTwCuuA= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= @@ -524,32 +523,30 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.42.0 h1:sYefIhrd/A3fO8rmr0vy2tgCLoR8CsbMqwbcUa70x00= -go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.42.0/go.mod h1:5Ll2ndRzg9UNUrj1n+v4ZCcrD/SYy7BnVrlCQXECowA= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 h1:pginetY7+onl4qN1vl0xW/V/v6OBZ0vVdH+esuJgvmM= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0/go.mod h1:XiYsayHc36K3EByOO6nbAXnAWbrUxdjUROCEeeROOH8= -go.opentelemetry.io/contrib/propagators/b3 v1.17.0 h1:ImOVvHnku8jijXqkwCSyYKRDt2YrnGXD4BbhcpfbfJo= -go.opentelemetry.io/otel v1.16.0 h1:Z7GVAX/UkAXPKsy94IU+i6thsQS4nb7LviLpnaNeW8s= -go.opentelemetry.io/otel v1.16.0/go.mod h1:vl0h9NUa1D5s1nv3A5vZOYWn8av4K8Ml6JDeHrT/bx4= -go.opentelemetry.io/otel/exporters/jaeger v1.16.0 h1:YhxxmXZ011C0aDZKoNw+juVWAmEfv/0W2XBOv9aHTaA= -go.opentelemetry.io/otel/exporters/jaeger v1.16.0/go.mod h1:grYbBo/5afWlPpdPZYhyn78Bk04hnvxn2+hvxQhKIQM= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0 h1:t4ZwRPU+emrcvM2e9DHd0Fsf0JTPVcbfa/BhTDF03d0= -go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.16.0/go.mod h1:vLarbg68dH2Wa77g71zmKQqlQ8+8Rq3GRG31uc0WcWI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0 h1:cbsD4cUcviQGXdw8+bo5x2wazq10SKz8hEbtCRPcU78= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.16.0/go.mod h1:JgXSGah17croqhJfhByOLVY719k1emAXC8MVhCIJlRs= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0 h1:TVQp/bboR4mhZSav+MdgXB8FaRho1RC8UwVn3T0vjVc= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0/go.mod h1:I33vtIe0sR96wfrUcilIzLoA3mLHhRmz9S9Te0S3gDo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0 h1:iqjq9LAB8aK++sKVcELezzn655JnBNdsDhghU4G/So8= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.16.0/go.mod h1:hGXzO5bhhSHZnKvrDaXB82Y9DRFour0Nz/KrBh7reWw= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0 h1:+XWJd3jf75RXJq29mxbuXhCXFDG3S3R4vBUeSI2P7tE= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.16.0/go.mod h1:hqgzBPTf4yONMFgdZvL/bK42R/iinTyVQtiWihs3SZc= -go.opentelemetry.io/otel/metric v1.16.0 h1:RbrpwVG1Hfv85LgnZ7+txXioPDoh6EdbZHo26Q3hqOo= -go.opentelemetry.io/otel/metric v1.16.0/go.mod h1:QE47cpOmkwipPiefDwo2wDzwJrlfxxNYodqc4xnGCo4= -go.opentelemetry.io/otel/sdk v1.16.0 h1:Z1Ok1YsijYL0CSJpHt4cS3wDDh7p572grzNrBMiMWgE= -go.opentelemetry.io/otel/sdk v1.16.0/go.mod h1:tMsIuKXuuIWPBAOrH+eHtvhTL+SntFtXF9QD68aP6p4= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0 h1:9n9+SOwuCyZ0L8SbQYjZ5H+GKojHN3Kl8pBLwBUQqhk= +go.opentelemetry.io/contrib/instrumentation/github.com/labstack/echo/otelecho v0.44.0/go.mod h1:Wa9/q2K5L+ftWke2iekGNqVzwBWqyhI5OhtHKU7Qe04= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 h1:KfYpVmrjI7JuToy5k8XV3nkapjWx48k4E4JOtVstzQI= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0/go.mod h1:SeQhzAEccGVZVEy7aH87Nh0km+utSpo1pTv6eMMop48= +go.opentelemetry.io/contrib/propagators/b3 v1.19.0 h1:ulz44cpm6V5oAeg5Aw9HyqGFMS6XM7untlMEhD7YzzA= +go.opentelemetry.io/otel v1.18.0 h1:TgVozPGZ01nHyDZxK5WGPFB9QexeTMXEH7+tIClWfzs= +go.opentelemetry.io/otel v1.18.0/go.mod h1:9lWqYO0Db579XzVuCKFNPDl4s73Voa+zEck3wHaAYQI= +go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= +go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0 h1:IAtl+7gua134xcV3NieDhJHjjOVeJhXAnYf/0hswjUY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.18.0/go.mod h1:w+pXobnBzh95MNIkeIuAKcHe/Uu/CX2PKIvBP6ipKRA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0 h1:yE32ay7mJG2leczfREEhoW3VfSZIvHaB+gvVo1o8DQ8= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.18.0/go.mod h1:G17FHPDLt74bCI7tJ4CMitEk4BXTYG4FW6XUpkPBXa4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0 h1:6pu8ttx76BxHf+xz/H77AUZkPF3cwWzXqAUsXhVKI18= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.18.0/go.mod h1:IOmXxPrxoxFMXdNy7lfDmE8MzE61YPcurbUm0SMjerI= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0 h1:hSWWvDjXHVLq9DkmB+77fl8v7+t+yYiS+eNkiplDK54= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.18.0/go.mod h1:zG7KQql1WjZCaUJd+L/ReSYx4bjbYJxg5ws9ws+mYes= +go.opentelemetry.io/otel/metric v1.18.0 h1:JwVzw94UYmbx3ej++CwLUQZxEODDj/pOuTCvzhtRrSQ= +go.opentelemetry.io/otel/metric v1.18.0/go.mod h1:nNSpsVDjWGfb7chbRLUNW+PBNdcSTHD4Uu5pfFMOI0k= +go.opentelemetry.io/otel/sdk v1.18.0 h1:e3bAB0wB3MljH38sHzpV/qWrOTCFrdZF2ct9F8rBkcY= +go.opentelemetry.io/otel/sdk v1.18.0/go.mod h1:1RCygWV7plY2KmdskZEDDBs4tJeHG92MdHZIluiYs/M= go.opentelemetry.io/otel/sdk/metric v0.39.0 h1:Kun8i1eYf48kHH83RucG93ffz0zGV1sh46FAScOTuDI= -go.opentelemetry.io/otel/trace v1.16.0 h1:8JRpaObFoW0pxuVPapkgH8UhHQj+bJW8jJsCZEu5MQs= -go.opentelemetry.io/otel/trace v1.16.0/go.mod h1:Yt9vYq1SdNz3xdjZZK7wcXv1qv2pwLkqr2QVwea0ef0= +go.opentelemetry.io/otel/trace v1.18.0 h1:NY+czwbHbmndxojTEKiSMHkG2ClNH2PwmcHrdo0JY10= +go.opentelemetry.io/otel/trace v1.18.0/go.mod h1:T2+SGJGuYZY3bjj5rgh/hN7KIrlpWC5nS8Mjvzckz+0= 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.step.sm/crypto v0.35.0 h1:0N6ks5n1sdv4+biJMUTdqHjpTBKKN9zNqqBdOJIyHe4= @@ -568,8 +565,8 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= @@ -585,8 +582,8 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= -golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk= -golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -597,8 +594,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ= -golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -660,8 +657,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -671,8 +668,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= -golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -739,13 +736,13 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= 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.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -756,8 +753,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -818,8 +815,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= -golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -889,12 +886,12 @@ google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20230815205213-6bfd019c3878 h1:Iveh6tGCJkHAjJgEqUQYGDGgbwmhjoAOz8kO/ajxefY= -google.golang.org/genproto v0.0.0-20230815205213-6bfd019c3878/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= -google.golang.org/genproto/googleapis/api v0.0.0-20230815205213-6bfd019c3878 h1:WGq4lvB/mlicysM/dUT3SBvijH4D3sm/Ny1A4wmt2CI= -google.golang.org/genproto/googleapis/api v0.0.0-20230815205213-6bfd019c3878/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878 h1:lv6/DhyiFFGsmzxbsUUTOkN29II+zeWHxvT8Lpdxsv0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230815205213-6bfd019c3878/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb h1:Isk1sSH7bovx8Rti2wZK0UZF6oraBDK74uoyLEEVFN0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230913181813-007df8e322eb/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -911,8 +908,8 @@ google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.1 h1:OL+Vz23DTtrrldqHK49FUOPHyY75rvFqJfXC84NYW58= +google.golang.org/grpc v1.58.1/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/internal/graphapi/errors.go b/internal/graphapi/errors.go index ff984b817..4a2ef1153 100644 --- a/internal/graphapi/errors.go +++ b/internal/graphapi/errors.go @@ -2,8 +2,13 @@ package graphapi import "errors" -// ErrPortNumberInUse is returned when a port number is already in use. -var ErrPortNumberInUse = errors.New("port number already in use") +var ( + // ErrPortNumberInUse is returned when a port number is already in use. + ErrPortNumberInUse = errors.New("port number already in use") -// ErrRestrictedPortNumber is returned when a port number is restricted. -var ErrRestrictedPortNumber = errors.New("port number restricted") + // ErrRestrictedPortNumber is returned when a port number is restricted. + ErrRestrictedPortNumber = errors.New("port number restricted") + + // ErrInternalServerError is returned when an internal error occurs. + ErrInternalServerError = errors.New("internal server error") +) diff --git a/internal/graphapi/loadbalancer.resolvers.go b/internal/graphapi/loadbalancer.resolvers.go index 318f8c500..6a0aeb5ce 100644 --- a/internal/graphapi/loadbalancer.resolvers.go +++ b/internal/graphapi/loadbalancer.resolvers.go @@ -8,11 +8,12 @@ import ( "context" "database/sql" + "go.infratographer.com/permissions-api/pkg/permissions" + "go.infratographer.com/x/gidx" + "go.infratographer.com/load-balancer-api/internal/ent/generated" "go.infratographer.com/load-balancer-api/internal/ent/generated/port" "go.infratographer.com/load-balancer-api/internal/ent/generated/predicate" - "go.infratographer.com/permissions-api/pkg/permissions" - "go.infratographer.com/x/gidx" ) // LoadBalancerCreate is the resolver for the loadBalancerCreate field. @@ -23,7 +24,12 @@ func (r *mutationResolver) LoadBalancerCreate(ctx context.Context, input generat lb, err := r.client.LoadBalancer.Create().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + r.logger.Errorw("failed to create loadbalancer", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerCreatePayload{LoadBalancer: lb}, nil @@ -31,18 +37,30 @@ func (r *mutationResolver) LoadBalancerCreate(ctx context.Context, input generat // LoadBalancerUpdate is the resolver for the loadBalancerUpdate field. func (r *mutationResolver) LoadBalancerUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerInput) (*LoadBalancerUpdatePayload, error) { + logger := r.logger.With("loadbalancerID", id.String()) + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerUpdate); err != nil { return nil, err } lb, err := r.client.LoadBalancer.Get(ctx, id) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer", "error", err) + return nil, ErrInternalServerError } lb, err = lb.Update().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + logger.Errorw("failed to update loadbalancer", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerUpdatePayload{LoadBalancer: lb}, nil @@ -50,50 +68,52 @@ func (r *mutationResolver) LoadBalancerUpdate(ctx context.Context, id gidx.Prefi // LoadBalancerDelete is the resolver for the loadBalancerDelete field. func (r *mutationResolver) LoadBalancerDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerDeletePayload, error) { + logger := r.logger.With("loadbalancerID", id.String()) + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerDelete); err != nil { return nil, err } + if _, err := r.client.LoadBalancer.Get(ctx, id); err != nil { + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer", "error", err) + return nil, ErrInternalServerError + } + tx, err := r.client.BeginTx(ctx, &sql.TxOptions{}) if err != nil { - return nil, err + logger.Errorw("failed to begin transaction", "error", err) + return nil, ErrInternalServerError } + defer tx.Rollback() + // cleanup ports associated with loadbalancer ports, err := tx.Port.Query().Where(predicate.Port(port.LoadBalancerIDEQ(id))).All(ctx) if err != nil { - r.logger.Errorw("failed to query ports", "error", err) - if rerr := tx.Rollback(); rerr != nil { - r.logger.Errorw("failed to rollback transaction", "error", rerr, "stage", "query ports") - } - return nil, err + logger.Errorw("failed to query ports", "error", err) + return nil, ErrInternalServerError } for _, p := range ports { if err = tx.Port.DeleteOne(p).Exec(ctx); err != nil { - r.logger.Errorw("failed to delete port", "port", p.ID, "error", err) - if rerr := tx.Rollback(); rerr != nil { - r.logger.Errorw("failed to rollback transaction", "error", rerr, "stage", "delete port") - } - return nil, err + logger.Errorw("failed to delete port", "port", p.ID, "error", err) + return nil, ErrInternalServerError } } // delete loadbalancer if err = tx.LoadBalancer.DeleteOneID(id).Exec(ctx); err != nil { - r.logger.Errorw("failed to delete loadbalancer", "loadbalancer", id.String(), "error", err) - if rerr := tx.Rollback(); rerr != nil { - r.logger.Errorw("failed to rollback transaction", "error", rerr, "stage", "delete loadbalancer") - } - return nil, err + logger.Errorw("failed to delete loadbalancer", "error", err) + return nil, ErrInternalServerError } if err = tx.Commit(); err != nil { - r.logger.Errorw("failed to commit transaction", "error", err) - if rerr := tx.Rollback(); rerr != nil { - r.logger.Errorw("failed to rollback transaction", "error", rerr, "stage", "commit transaction") - } - return nil, err + logger.Errorw("failed to commit transaction", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerDeletePayload{DeletedID: id}, nil @@ -101,9 +121,21 @@ func (r *mutationResolver) LoadBalancerDelete(ctx context.Context, id gidx.Prefi // LoadBalancer is the resolver for the loadBalancer field. func (r *queryResolver) LoadBalancer(ctx context.Context, id gidx.PrefixedID) (*generated.LoadBalancer, error) { + logger := r.logger.With("loadbalancerID", id.String()) + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerGet); err != nil { return nil, err } - return r.client.LoadBalancer.Get(ctx, id) + lb, err := r.client.LoadBalancer.Get(ctx, id) + if err != nil { + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer", "error", err) + return nil, ErrInternalServerError + } + + return lb, nil } diff --git a/internal/graphapi/loadbalancer_test.go b/internal/graphapi/loadbalancer_test.go index e1dde2e9e..7c509bff8 100644 --- a/internal/graphapi/loadbalancer_test.go +++ b/internal/graphapi/loadbalancer_test.go @@ -164,16 +164,17 @@ func TestUpdate_loadBalancer(t *testing.T) { lb := (&LoadBalancerBuilder{}).MustNew(ctx) updateName := gofakeit.DomainName() - emptyName := "" testCases := []struct { TestName string + ID gidx.PrefixedID Input graphclient.UpdateLoadBalancerInput ExpectedLB *ent.LoadBalancer errorMsg string }{ { TestName: "updates loadbalancer", + ID: lb.ID, Input: graphclient.UpdateLoadBalancerInput{Name: &updateName}, ExpectedLB: &ent.LoadBalancer{ Name: updateName, @@ -184,14 +185,21 @@ func TestUpdate_loadBalancer(t *testing.T) { }, { TestName: "fails to update name to empty", - Input: graphclient.UpdateLoadBalancerInput{Name: &emptyName}, + ID: lb.ID, + Input: graphclient.UpdateLoadBalancerInput{Name: newString("")}, errorMsg: "value is less than the required length", }, + { + TestName: "fails to update loadbalancer that does not exist", + ID: gidx.PrefixedID("loadbal-dne"), + Input: graphclient.UpdateLoadBalancerInput{Name: newString("loadbal-dne")}, + errorMsg: "load_balancer not found", + }, } for _, tt := range testCases { t.Run(tt.TestName, func(t *testing.T) { - resp, err := graphTestClient().LoadBalancerUpdate(ctx, lb.ID, tt.Input) + resp, err := graphTestClient().LoadBalancerUpdate(ctx, tt.ID, tt.Input) if tt.errorMsg != "" { require.Error(t, err) From ccd7fabd9bb417674125823dda6af72ef2fe4161 Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Fri, 22 Sep 2023 21:40:46 +0000 Subject: [PATCH 03/10] origin error logs, do no expose internals Signed-off-by: Matt Siwiec --- internal/graphapi/origin.resolvers.go | 47 +++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/internal/graphapi/origin.resolvers.go b/internal/graphapi/origin.resolvers.go index aa00f863c..5c5c06e2e 100644 --- a/internal/graphapi/origin.resolvers.go +++ b/internal/graphapi/origin.resolvers.go @@ -7,13 +7,16 @@ package graphapi import ( "context" - "go.infratographer.com/load-balancer-api/internal/ent/generated" "go.infratographer.com/permissions-api/pkg/permissions" "go.infratographer.com/x/gidx" + + "go.infratographer.com/load-balancer-api/internal/ent/generated" ) // LoadBalancerOriginCreate is the resolver for the loadBalancerOriginCreate field. func (r *mutationResolver) LoadBalancerOriginCreate(ctx context.Context, input generated.CreateLoadBalancerOriginInput) (*LoadBalancerOriginCreatePayload, error) { + logger := r.logger.With("poolID", input.PoolID) + if err := permissions.CheckAccess(ctx, input.PoolID, actionLoadBalancerPoolUpdate); err != nil { return nil, err } @@ -21,12 +24,22 @@ func (r *mutationResolver) LoadBalancerOriginCreate(ctx context.Context, input g // check if pool exists _, err := r.client.Pool.Get(ctx, input.PoolID) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get pool", "error", err) + return nil, ErrInternalServerError } origin, err := r.client.Origin.Create().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + logger.Errorw("failed to create origin", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerOriginCreatePayload{LoadBalancerOrigin: origin}, nil @@ -34,9 +47,16 @@ func (r *mutationResolver) LoadBalancerOriginCreate(ctx context.Context, input g // LoadBalancerOriginUpdate is the resolver for the loadBalancerOriginUpdate field. func (r *mutationResolver) LoadBalancerOriginUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerOriginInput) (*LoadBalancerOriginUpdatePayload, error) { + logger := r.logger.With("originID", id.String()) + origin, err := r.client.Origin.Get(ctx, id) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get origin", "error", err) + return nil, ErrInternalServerError } if err := permissions.CheckAccess(ctx, origin.PoolID, actionLoadBalancerPoolUpdate); err != nil { @@ -45,7 +65,12 @@ func (r *mutationResolver) LoadBalancerOriginUpdate(ctx context.Context, id gidx origin, err = origin.Update().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + logger.Errorw("failed to update origin", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerOriginUpdatePayload{LoadBalancerOrigin: origin}, nil @@ -53,9 +78,16 @@ func (r *mutationResolver) LoadBalancerOriginUpdate(ctx context.Context, id gidx // LoadBalancerOriginDelete is the resolver for the loadBalancerOriginDelete field. func (r *mutationResolver) LoadBalancerOriginDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerOriginDeletePayload, error) { + logger := r.logger.With("originID", id.String()) + origin, err := r.client.Origin.Get(ctx, id) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get origin", "error", err) + return nil, ErrInternalServerError } if err := permissions.CheckAccess(ctx, origin.PoolID, actionLoadBalancerPoolUpdate); err != nil { @@ -63,7 +95,8 @@ func (r *mutationResolver) LoadBalancerOriginDelete(ctx context.Context, id gidx } if err := r.client.Origin.DeleteOneID(id).Exec(ctx); err != nil { - return nil, err + logger.Errorw("failed to delete origin", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerOriginDeletePayload{DeletedID: id}, nil From d7f486af428b3315f4cb0ab0e72a6bcca4d4e139 Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Fri, 22 Sep 2023 22:00:09 +0000 Subject: [PATCH 04/10] handle invalid gidx Signed-off-by: Matt Siwiec --- internal/graphapi/loadbalancer.resolvers.go | 15 +++++++++++++++ internal/graphapi/loadbalancer_test.go | 16 ++++++++++++++++ internal/graphapi/origin.resolvers.go | 15 +++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/internal/graphapi/loadbalancer.resolvers.go b/internal/graphapi/loadbalancer.resolvers.go index 6a0aeb5ce..01d4a017f 100644 --- a/internal/graphapi/loadbalancer.resolvers.go +++ b/internal/graphapi/loadbalancer.resolvers.go @@ -39,6 +39,11 @@ func (r *mutationResolver) LoadBalancerCreate(ctx context.Context, input generat func (r *mutationResolver) LoadBalancerUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerInput) (*LoadBalancerUpdatePayload, error) { logger := r.logger.With("loadbalancerID", id.String()) + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerUpdate); err != nil { return nil, err } @@ -70,6 +75,11 @@ func (r *mutationResolver) LoadBalancerUpdate(ctx context.Context, id gidx.Prefi func (r *mutationResolver) LoadBalancerDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerDeletePayload, error) { logger := r.logger.With("loadbalancerID", id.String()) + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerDelete); err != nil { return nil, err } @@ -123,6 +133,11 @@ func (r *mutationResolver) LoadBalancerDelete(ctx context.Context, id gidx.Prefi func (r *queryResolver) LoadBalancer(ctx context.Context, id gidx.PrefixedID) (*generated.LoadBalancer, error) { logger := r.logger.With("loadbalancerID", id.String()) + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerGet); err != nil { return nil, err } diff --git a/internal/graphapi/loadbalancer_test.go b/internal/graphapi/loadbalancer_test.go index 7c509bff8..5a242c822 100644 --- a/internal/graphapi/loadbalancer_test.go +++ b/internal/graphapi/loadbalancer_test.go @@ -50,6 +50,11 @@ func TestQuery_loadBalancer(t *testing.T) { QueryID: gidx.MustNewID("testing"), errorMsg: "load_balancer not found", }, + { + TestName: "invalid gidx format", + QueryID: "test-invalid-id", + errorMsg: "invalid id", + }, } for _, tt := range testCases { @@ -195,6 +200,12 @@ func TestUpdate_loadBalancer(t *testing.T) { Input: graphclient.UpdateLoadBalancerInput{Name: newString("loadbal-dne")}, errorMsg: "load_balancer not found", }, + { + TestName: "fails with invalid gidx", + ID: "test-invalid-id", + Input: graphclient.UpdateLoadBalancerInput{Name: newString("loadbal-dne")}, + errorMsg: "invalid id", + }, } for _, tt := range testCases { @@ -254,6 +265,11 @@ func TestDelete_loadBalancer(t *testing.T) { Input: gidx.PrefixedID(""), errorMsg: "load_balancer not found", }, + { + TestName: "fails with invalid id", + Input: "test-invalid-id", + errorMsg: "invalid id", + }, } for _, tt := range testCases { diff --git a/internal/graphapi/origin.resolvers.go b/internal/graphapi/origin.resolvers.go index 5c5c06e2e..e4a77a005 100644 --- a/internal/graphapi/origin.resolvers.go +++ b/internal/graphapi/origin.resolvers.go @@ -21,6 +21,11 @@ func (r *mutationResolver) LoadBalancerOriginCreate(ctx context.Context, input g return nil, err } + // check gidx format + if _, err := gidx.Parse(input.PoolID.String()); err != nil { + return nil, err + } + // check if pool exists _, err := r.client.Pool.Get(ctx, input.PoolID) if err != nil { @@ -49,6 +54,11 @@ func (r *mutationResolver) LoadBalancerOriginCreate(ctx context.Context, input g func (r *mutationResolver) LoadBalancerOriginUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerOriginInput) (*LoadBalancerOriginUpdatePayload, error) { logger := r.logger.With("originID", id.String()) + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + origin, err := r.client.Origin.Get(ctx, id) if err != nil { if generated.IsNotFound(err) { @@ -80,6 +90,11 @@ func (r *mutationResolver) LoadBalancerOriginUpdate(ctx context.Context, id gidx func (r *mutationResolver) LoadBalancerOriginDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerOriginDeletePayload, error) { logger := r.logger.With("originID", id.String()) + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + origin, err := r.client.Origin.Get(ctx, id) if err != nil { if generated.IsNotFound(err) { From 175fe898ad3fd37ff614819e54577d23dc7a6d7f Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Mon, 25 Sep 2023 19:51:00 +0000 Subject: [PATCH 05/10] pool error logs, do no expose internals Signed-off-by: Matt Siwiec --- internal/graphapi/loadbalancer_test.go | 2 +- internal/graphapi/pool.resolvers.go | 114 ++++++++++++++++++------- internal/graphapi/pool_test.go | 39 +++++++-- 3 files changed, 115 insertions(+), 40 deletions(-) diff --git a/internal/graphapi/loadbalancer_test.go b/internal/graphapi/loadbalancer_test.go index 5a242c822..e9647a726 100644 --- a/internal/graphapi/loadbalancer_test.go +++ b/internal/graphapi/loadbalancer_test.go @@ -266,7 +266,7 @@ func TestDelete_loadBalancer(t *testing.T) { errorMsg: "load_balancer not found", }, { - TestName: "fails with invalid id", + TestName: "fails with invalid gidx", Input: "test-invalid-id", errorMsg: "invalid id", }, diff --git a/internal/graphapi/pool.resolvers.go b/internal/graphapi/pool.resolvers.go index 818fe0b3f..e7e167ba7 100644 --- a/internal/graphapi/pool.resolvers.go +++ b/internal/graphapi/pool.resolvers.go @@ -7,14 +7,13 @@ package graphapi import ( "context" "database/sql" - "fmt" - "github.com/labstack/gommon/log" + "go.infratographer.com/permissions-api/pkg/permissions" + "go.infratographer.com/x/gidx" + "go.infratographer.com/load-balancer-api/internal/ent/generated" "go.infratographer.com/load-balancer-api/internal/ent/generated/origin" "go.infratographer.com/load-balancer-api/internal/ent/generated/predicate" - "go.infratographer.com/permissions-api/pkg/permissions" - "go.infratographer.com/x/gidx" ) // LoadBalancerPoolCreate is the resolver for the LoadBalancerPoolCreate field. @@ -23,9 +22,19 @@ func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input gen return nil, err } + // check gidx owner format + if _, err := gidx.Parse(input.OwnerID.String()); err != nil { + return nil, err + } + pool, err := r.client.Pool.Create().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + r.logger.Errorw("failed to create loadbalancer", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerPoolCreatePayload{LoadBalancerPool: pool}, nil @@ -33,18 +42,35 @@ func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input gen // LoadBalancerPoolUpdate is the resolver for the LoadBalancerPoolUpdate field. func (r *mutationResolver) LoadBalancerPoolUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerPoolInput) (*LoadBalancerPoolUpdatePayload, error) { + logger := r.logger.With("loadbalancerPoolID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerPoolUpdate); err != nil { return nil, err } pool, err := r.client.Pool.Get(ctx, id) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer pool", "error", err) + return nil, ErrInternalServerError } pool, err = pool.Update().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + logger.Errorw("failed to update loadbalancer pool", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerPoolUpdatePayload{LoadBalancerPool: pool}, nil @@ -52,54 +78,59 @@ func (r *mutationResolver) LoadBalancerPoolUpdate(ctx context.Context, id gidx.P // LoadBalancerPoolDelete is the resolver for the loadBalancerPoolDelete field. func (r *mutationResolver) LoadBalancerPoolDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerPoolDeletePayload, error) { + logger := r.logger.With("loadbalancerPoolID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerPoolDelete); err != nil { return nil, err } - // TODO: return the requestID echo generates or we could use the root trace id - var ( - err error - tx *generated.Tx - ) + if _, err := r.client.Pool.Get(ctx, id); err != nil { + if generated.IsNotFound(err) { + return nil, err + } - tx, err = r.client.BeginTx(ctx, &sql.TxOptions{}) + logger.Errorw("failed to get loadbalancer pool", "error", err) + return nil, ErrInternalServerError + } + + tx, err := r.client.BeginTx(ctx, &sql.TxOptions{}) if err != nil { - return nil, err + logger.Errorw("failed to begin transaction", "error", err) + return nil, ErrInternalServerError } + defer tx.Rollback() + // todo: cleanup pool assigments // cleanup origins associated with pool origins, err := tx.Origin.Query().Where(predicate.Origin(origin.PoolIDEQ(id))).All(ctx) if err != nil { - if rerr := tx.Rollback(); rerr != nil { - log.Error(fmt.Errorf("%w: %v", err, rerr).Error()) - } - return nil, err + logger.Errorw("failed to query origins", "error", err) + return nil, ErrInternalServerError } for _, o := range origins { if err = tx.Origin.DeleteOne(o).Exec(ctx); err != nil { - if rerr := tx.Rollback(); rerr != nil { - log.Error(fmt.Errorf("%w: %v", err, rerr).Error()) - } - return nil, err + logger.Errorw("failed to delete origin", "origin", o.ID, "error", err) + return nil, ErrInternalServerError } } // delete pool - if err = tx.Pool.DeleteOneID(id).Exec(ctx); err != nil { - if rerr := tx.Rollback(); rerr != nil { - log.Error(fmt.Errorf("%w: %v", err, rerr).Error()) - } - return nil, err + if err := tx.Pool.DeleteOneID(id).Exec(ctx); err != nil { + logger.Errorw("failed to delete loadbalancer pool", "error", err) + return nil, ErrInternalServerError } - if err = tx.Commit(); err != nil { - if rerr := tx.Rollback(); rerr != nil { - log.Error(fmt.Errorf("%w: %v", err, rerr).Error()) - } - return nil, err + if err := tx.Commit(); err != nil { + logger.Errorw("failed to commit transaction", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerPoolDeletePayload{DeletedID: &id}, nil @@ -107,9 +138,26 @@ func (r *mutationResolver) LoadBalancerPoolDelete(ctx context.Context, id gidx.P // LoadBalancerPool is the resolver for the loadBalancerPool field. func (r *queryResolver) LoadBalancerPool(ctx context.Context, id gidx.PrefixedID) (*generated.Pool, error) { + logger := r.logger.With("loadbalancerPoolID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerPoolGet); err != nil { return nil, err } - return r.client.Pool.Get(ctx, id) + pool, err := r.client.Pool.Get(ctx, id) + if err != nil { + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer pool", "error", err) + return nil, ErrInternalServerError + } + + return pool, nil } diff --git a/internal/graphapi/pool_test.go b/internal/graphapi/pool_test.go index fe75e365e..9ad664f22 100644 --- a/internal/graphapi/pool_test.go +++ b/internal/graphapi/pool_test.go @@ -47,11 +47,11 @@ func TestQueryPool(t *testing.T) { }, { TestName: "pool not found", - QueryID: gidx.MustNewID("testing"), + QueryID: gidx.MustNewID("loadpol"), errorMsg: "not found", }, { - TestName: "invalid pool query ID", + TestName: "invalid pool ID", QueryID: "an invalid pool id", errorMsg: "invalid id", }, @@ -178,12 +178,14 @@ func TestMutate_PoolUpdate(t *testing.T) { testCases := []struct { TestName string + ID gidx.PrefixedID Input graphclient.UpdateLoadBalancerPoolInput ExpectedPool ent.LoadBalancerPool errorMsg string }{ { TestName: "successfully updates name", + ID: pool1.ID, Input: graphclient.UpdateLoadBalancerPoolInput{ Name: newString("ImaPool"), }, @@ -195,6 +197,7 @@ func TestMutate_PoolUpdate(t *testing.T) { }, { TestName: "successfully updates protocol", + ID: pool1.ID, Input: graphclient.UpdateLoadBalancerPoolInput{ Name: newString("ImaPool"), Protocol: &updateProtocolUDP, @@ -207,11 +210,24 @@ func TestMutate_PoolUpdate(t *testing.T) { }, { TestName: "empty name", + ID: pool1.ID, Input: graphclient.UpdateLoadBalancerPoolInput{ Name: newString(""), }, errorMsg: "validator failed", }, + { + TestName: "fails with invalid gidx", + ID: gidx.PrefixedID("not a valid gidx"), + Input: graphclient.UpdateLoadBalancerPoolInput{}, + errorMsg: "invalid id", + }, + { + TestName: "fails to update pool that does not exist", + ID: gidx.MustNewID("loadpol"), + Input: graphclient.UpdateLoadBalancerPoolInput{}, + errorMsg: "not found", + }, } for _, tt := range testCases { @@ -219,7 +235,7 @@ func TestMutate_PoolUpdate(t *testing.T) { tt := tt t.Run(tt.TestName, func(t *testing.T) { - updatedPoolResp, err := graphTestClient().LoadBalancerPoolUpdate(ctx, pool1.ID, tt.Input) + updatedPoolResp, err := graphTestClient().LoadBalancerPoolUpdate(ctx, tt.ID, tt.Input) if tt.errorMsg != "" { require.Error(t, err) assert.ErrorContains(t, err, tt.errorMsg) @@ -251,6 +267,8 @@ func TestMutate_PoolDelete(t *testing.T) { ctx = context.WithValue(ctx, permissions.CheckerCtxKey, permissions.DefaultAllowChecker) pool1 := (&PoolBuilder{Protocol: "tcp"}).MustNew(ctx) + pool2 := (&PoolBuilder{Protocol: "tcp"}).MustNew(ctx) + _ = (&OriginBuilder{PoolID: pool2.ID}).MustNew(ctx) testCases := []struct { TestName string @@ -262,15 +280,24 @@ func TestMutate_PoolDelete(t *testing.T) { DeleteID: pool1.ID, }, { - TestName: "invalid ID", + TestName: "fails with invalid gidx", DeleteID: "not a valid ID", errorMsg: "invalid id", }, { - TestName: "non-existent ID", - DeleteID: gidx.MustNewID(ownerPrefix), + TestName: "fails to delete pool that does not exist", + DeleteID: gidx.MustNewID("loadpol"), errorMsg: "not found", }, + { + TestName: "fails to delete empty pool id", + DeleteID: gidx.PrefixedID(""), + errorMsg: "not found", + }, + { + TestName: "deletes pool with associated origins", + DeleteID: pool2.ID, + }, } for _, tt := range testCases { From 33aca57d5159718db0d28db6b3b6099dce665b8a Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Mon, 25 Sep 2023 23:38:49 +0000 Subject: [PATCH 06/10] port error logs, do no expose internals Signed-off-by: Matt Siwiec --- internal/graphapi/pool.resolvers.go | 8 ++-- internal/graphapi/port.resolvers.go | 62 +++++++++++++++++++++++++---- internal/graphapi/port_test.go | 37 ++++++++++++++++- 3 files changed, 94 insertions(+), 13 deletions(-) diff --git a/internal/graphapi/pool.resolvers.go b/internal/graphapi/pool.resolvers.go index e7e167ba7..f6c08add2 100644 --- a/internal/graphapi/pool.resolvers.go +++ b/internal/graphapi/pool.resolvers.go @@ -18,12 +18,12 @@ import ( // LoadBalancerPoolCreate is the resolver for the LoadBalancerPoolCreate field. func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input generated.CreateLoadBalancerPoolInput) (*LoadBalancerPoolCreatePayload, error) { - if err := permissions.CheckAccess(ctx, input.OwnerID, actionLoadBalancerPoolCreate); err != nil { + // check gidx owner format + if _, err := gidx.Parse(input.OwnerID.String()); err != nil { return nil, err } - // check gidx owner format - if _, err := gidx.Parse(input.OwnerID.String()); err != nil { + if err := permissions.CheckAccess(ctx, input.OwnerID, actionLoadBalancerPoolCreate); err != nil { return nil, err } @@ -33,7 +33,7 @@ func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input gen return nil, err } - r.logger.Errorw("failed to create loadbalancer", "error", err) + r.logger.Errorw("failed to create loadbalancer pool", "error", err) return nil, ErrInternalServerError } diff --git a/internal/graphapi/port.resolvers.go b/internal/graphapi/port.resolvers.go index 9d1960d63..6438261ad 100644 --- a/internal/graphapi/port.resolvers.go +++ b/internal/graphapi/port.resolvers.go @@ -8,13 +8,26 @@ import ( "context" "strings" - "go.infratographer.com/load-balancer-api/internal/ent/generated" "go.infratographer.com/permissions-api/pkg/permissions" "go.infratographer.com/x/gidx" + + "go.infratographer.com/load-balancer-api/internal/ent/generated" ) // LoadBalancerPortCreate is the resolver for the loadBalancerPortCreate field. func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input generated.CreateLoadBalancerPortInput) (*LoadBalancerPortCreatePayload, error) { + // check gidx lb id format + if _, err := gidx.Parse(input.LoadBalancerID.String()); err != nil { + return nil, err + } + + // check gidx pool id format + for _, p := range input.PoolIDs { + if _, err := gidx.Parse(p.String()); err != nil { + return nil, err + } + } + if err := permissions.CheckAccess(ctx, input.LoadBalancerID, actionLoadBalancerUpdate); err != nil { return nil, err } @@ -24,8 +37,11 @@ func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input gen switch { case generated.IsConstraintError(err) && strings.Contains(err.Error(), "number"): return nil, ErrPortNumberInUse - default: + case generated.IsValidationError(err): return nil, err + default: + r.logger.Errorw("failed to create loadbalancer port", "error", err) + return nil, ErrInternalServerError } } @@ -34,20 +50,37 @@ func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input gen // LoadBalancerPortUpdate is the resolver for the loadBalancerPortUpdate field. func (r *mutationResolver) LoadBalancerPortUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerPortInput) (*LoadBalancerPortUpdatePayload, error) { + logger := r.logger.With("loadbalancerPortID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + p, err := r.client.Port.Get(ctx, id) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer port", "error", err) + return nil, ErrInternalServerError } + if err := permissions.CheckAccess(ctx, p.LoadBalancerID, actionLoadBalancerUpdate); err != nil { return nil, err } p, err = p.Update().SetInput(input).Save(ctx) if err != nil { - if generated.IsConstraintError(err) && strings.Contains(err.Error(), "number") { - return nil, ErrPortNumberInUse - } else { + switch { + case generated.IsValidationError(err): return nil, err + case generated.IsConstraintError(err) && strings.Contains(err.Error(), "number"): + return nil, ErrPortNumberInUse + default: + logger.Errorw("failed to update loadbalancer port", "error", err) + return nil, ErrInternalServerError } } @@ -56,9 +89,21 @@ func (r *mutationResolver) LoadBalancerPortUpdate(ctx context.Context, id gidx.P // LoadBalancerPortDelete is the resolver for the loadBalancerPortDelete field. func (r *mutationResolver) LoadBalancerPortDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerPortDeletePayload, error) { + logger := r.logger.With("loadbalancerPortID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + p, err := r.client.Port.Get(ctx, id) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer port", "error", err) + return nil, ErrInternalServerError } if err := permissions.CheckAccess(ctx, p.LoadBalancerID, actionLoadBalancerUpdate); err != nil { @@ -66,7 +111,8 @@ func (r *mutationResolver) LoadBalancerPortDelete(ctx context.Context, id gidx.P } if err := r.client.Port.DeleteOneID(id).Exec(ctx); err != nil { - return nil, err + logger.Errorw("failed to delete loadbalancer port", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerPortDeletePayload{DeletedID: id}, nil diff --git a/internal/graphapi/port_test.go b/internal/graphapi/port_test.go index 0cdc34825..7ee46308f 100644 --- a/internal/graphapi/port_test.go +++ b/internal/graphapi/port_test.go @@ -104,6 +104,16 @@ func TestCreate_LoadbalancerPort(t *testing.T) { }, errorMsg: "port number restricted", }, + { + TestName: "fails to create loadbalancer port with invalid pool id", + Input: graphclient.CreateLoadBalancerPortInput{ + Name: "lb-port", + LoadBalancerID: lb.ID, + Number: 1234, + PoolIDs: []gidx.PrefixedID{"not-a-valid-pool-id"}, + }, + errorMsg: "invalid id", + }, } for _, tt := range testCases { @@ -154,11 +164,13 @@ func TestUpdate_LoadbalancerPort(t *testing.T) { testCases := []struct { TestName string Input graphclient.UpdateLoadBalancerPortInput + ID gidx.PrefixedID Expected *graphclient.LoadBalancerPort errorMsg string }{ { TestName: "fails to update loadbalancer port number to duplicate of another port", + ID: port.ID, Input: graphclient.UpdateLoadBalancerPortInput{ Number: newInt64(8080), }, @@ -166,6 +178,7 @@ func TestUpdate_LoadbalancerPort(t *testing.T) { }, { TestName: "fails to update loadbalancer port number to restricted port", + ID: port.ID, Input: graphclient.UpdateLoadBalancerPortInput{ Number: newInt64(1234), }, @@ -173,6 +186,7 @@ func TestUpdate_LoadbalancerPort(t *testing.T) { }, { TestName: "updates loadbalancer port name", + ID: port.ID, Input: graphclient.UpdateLoadBalancerPortInput{ Name: newString("lb-port"), }, @@ -183,6 +197,7 @@ func TestUpdate_LoadbalancerPort(t *testing.T) { }, { TestName: "updates loadbalancer port number", + ID: port.ID, Input: graphclient.UpdateLoadBalancerPortInput{ Number: newInt64(22), }, @@ -193,6 +208,7 @@ func TestUpdate_LoadbalancerPort(t *testing.T) { }, { TestName: "fails to update loadbalancer port name to empty", + ID: port.ID, Input: graphclient.UpdateLoadBalancerPortInput{ Name: newString(""), }, @@ -200,6 +216,7 @@ func TestUpdate_LoadbalancerPort(t *testing.T) { }, { TestName: "fails to update loadbalancer port number < min", + ID: port.ID, Input: graphclient.UpdateLoadBalancerPortInput{ Number: newInt64(0), }, @@ -207,16 +224,29 @@ func TestUpdate_LoadbalancerPort(t *testing.T) { }, { TestName: "fails to update loadbalancer port number > max", + ID: port.ID, Input: graphclient.UpdateLoadBalancerPortInput{ Number: newInt64(65536), }, errorMsg: "value out of range", }, + { + TestName: "fails to update port that does not exist", + ID: gidx.PrefixedID("loadprt-doesnotexist"), + Input: graphclient.UpdateLoadBalancerPortInput{}, + errorMsg: "not found", + }, + { + TestName: "fails to update port with invalid gidx", + ID: gidx.PrefixedID("not a valid gidx"), + Input: graphclient.UpdateLoadBalancerPortInput{}, + errorMsg: "invalid id", + }, } for _, tt := range testCases { t.Run(tt.TestName, func(t *testing.T) { - resp, err := graphTestClient().LoadBalancerPortUpdate(ctx, port.ID, tt.Input) + resp, err := graphTestClient().LoadBalancerPortUpdate(ctx, tt.ID, tt.Input) if tt.errorMsg != "" { require.Error(t, err) @@ -272,6 +302,11 @@ func TestDelete_LoadbalancerPort(t *testing.T) { Input: gidx.PrefixedID(""), errorMsg: "port not found", }, + { + TestName: "fails to delete with invalid gidx port ID", + Input: gidx.PrefixedID("not-a-valid-gidx"), + errorMsg: "invalid id", + }, } for _, tt := range testCases { From dacc5b50e8c19ef3eb4e2e5641d7e7896d06f7ce Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Tue, 26 Sep 2023 00:00:11 +0000 Subject: [PATCH 07/10] provider error logs, do no expose internals Signed-off-by: Matt Siwiec --- internal/graphapi/provider.resolvers.go | 68 +++++++++++++++++++++++-- internal/graphapi/provider_test.go | 37 ++++++++++++-- 2 files changed, 96 insertions(+), 9 deletions(-) diff --git a/internal/graphapi/provider.resolvers.go b/internal/graphapi/provider.resolvers.go index 2322c08dc..3db23f3fd 100644 --- a/internal/graphapi/provider.resolvers.go +++ b/internal/graphapi/provider.resolvers.go @@ -7,20 +7,31 @@ package graphapi import ( "context" - "go.infratographer.com/load-balancer-api/internal/ent/generated" "go.infratographer.com/permissions-api/pkg/permissions" "go.infratographer.com/x/gidx" + + "go.infratographer.com/load-balancer-api/internal/ent/generated" ) // LoadBalancerProviderCreate is the resolver for the loadBalancerProviderCreate field. func (r *mutationResolver) LoadBalancerProviderCreate(ctx context.Context, input generated.CreateLoadBalancerProviderInput) (*LoadBalancerProviderCreatePayload, error) { + // check gidx owner format + if _, err := gidx.Parse(input.OwnerID.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, input.OwnerID, actionLoadBalancerProviderCreate); err != nil { return nil, err } p, err := r.client.Provider.Create().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + r.logger.Errorw("failed to create loadbalancer provider", "error", err) + return nil, ErrInternalServerError } return &LoadBalancerProviderCreatePayload{LoadBalancerProvider: p}, nil @@ -28,29 +39,59 @@ func (r *mutationResolver) LoadBalancerProviderCreate(ctx context.Context, input // LoadBalancerProviderUpdate is the resolver for the loadBalancerProviderUpdate field. func (r *mutationResolver) LoadBalancerProviderUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerProviderInput) (*LoadBalancerProviderUpdatePayload, error) { + logger := r.logger.With("loadbalancerProviderID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerProviderUpdate); err != nil { return nil, err } p, err := r.client.Provider.Get(ctx, id) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer provider", "error", err) + return nil, ErrInternalServerError } p, err = p.Update().SetInput(input).Save(ctx) if err != nil { - return nil, err + if generated.IsValidationError(err) { + return nil, err + } + + logger.Errorw("failed to update loadbalancer provider", "error", err) + return nil, ErrInternalServerError } + return &LoadBalancerProviderUpdatePayload{LoadBalancerProvider: p}, nil } // LoadBalancerProviderDelete is the resolver for the loadBalancerProviderDelete field. func (r *mutationResolver) LoadBalancerProviderDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerProviderDeletePayload, error) { + logger := r.logger.With("loadbalancerProviderID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerProviderDelete); err != nil { return nil, err } if err := r.client.Provider.DeleteOneID(id).Exec(ctx); err != nil { + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to delete loadbalancer provider", "error", err) return nil, err } @@ -59,9 +100,26 @@ func (r *mutationResolver) LoadBalancerProviderDelete(ctx context.Context, id gi // LoadBalancerProvider is the resolver for the loadBalancerProvider field. func (r *queryResolver) LoadBalancerProvider(ctx context.Context, id gidx.PrefixedID) (*generated.Provider, error) { + logger := r.logger.With("loadbalancerProviderID", id.String()) + + // check gidx format + if _, err := gidx.Parse(id.String()); err != nil { + return nil, err + } + if err := permissions.CheckAccess(ctx, id, actionLoadBalancerProviderGet); err != nil { return nil, err } - return r.client.Provider.Get(ctx, id) + p, err := r.client.Provider.Get(ctx, id) + if err != nil { + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer provider", "error", err) + return nil, ErrInternalServerError + } + + return p, nil } diff --git a/internal/graphapi/provider_test.go b/internal/graphapi/provider_test.go index e60f727f1..3bd1574e7 100644 --- a/internal/graphapi/provider_test.go +++ b/internal/graphapi/provider_test.go @@ -44,6 +44,11 @@ func TestQuery_loadBalancerProvider(t *testing.T) { QueryID: gidx.MustNewID("testing"), errorMsg: "provider not found", }, + { + TestName: "Invalid load balancer provider ID", + QueryID: gidx.PrefixedID("invalid"), + errorMsg: "invalid id", + }, } for _, tt := range testCases { @@ -102,6 +107,11 @@ func TestCreate_Provider(t *testing.T) { Input: graphclient.CreateLoadBalancerProviderInput{Name: name, OwnerID: ""}, errorMsg: "value is less than the required length", }, + { + TestName: "fails to create provider with invalid ownerID", + Input: graphclient.CreateLoadBalancerProviderInput{Name: name, OwnerID: gidx.PrefixedID("invalid")}, + errorMsg: "invalid id", + }, } for _, tt := range testCases { @@ -139,16 +149,17 @@ func TestUpdate_Provider(t *testing.T) { prov := ProviderBuilder{}.MustNew(ctx) updateName := gofakeit.DomainName() - emptyName := "" testCases := []struct { TestName string + ID gidx.PrefixedID Input graphclient.UpdateLoadBalancerProviderInput ExpectedProvider *ent.LoadBalancerProvider errorMsg string }{ { TestName: "updates provider", + ID: prov.ID, Input: graphclient.UpdateLoadBalancerProviderInput{Name: &updateName}, ExpectedProvider: &ent.LoadBalancerProvider{ Name: updateName, @@ -158,14 +169,27 @@ func TestUpdate_Provider(t *testing.T) { }, { TestName: "fails to update name to empty", - Input: graphclient.UpdateLoadBalancerProviderInput{Name: &emptyName}, + ID: prov.ID, + Input: graphclient.UpdateLoadBalancerProviderInput{Name: newString("")}, errorMsg: "value is less than the required length", }, + { + TestName: "fails to update provider that does not exist", + ID: gidx.PrefixedID("loadpvd-dne"), + Input: graphclient.UpdateLoadBalancerProviderInput{}, + errorMsg: "provider not found", + }, + { + TestName: "fails to update provider with invalid id", + ID: gidx.PrefixedID("invalid"), + Input: graphclient.UpdateLoadBalancerProviderInput{}, + errorMsg: "invalid id", + }, } for _, tt := range testCases { t.Run(tt.TestName, func(t *testing.T) { - resp, err := graphTestClient().LoadBalancerProviderUpdate(ctx, prov.ID, tt.Input) + resp, err := graphTestClient().LoadBalancerProviderUpdate(ctx, tt.ID, tt.Input) if tt.errorMsg != "" { require.Error(t, err) @@ -215,11 +239,16 @@ func TestDelete_Provider(t *testing.T) { Input: gidx.PrefixedID(""), errorMsg: "provider not found", }, + { + TestName: "fails to delete invalid gidx id", + Input: gidx.PrefixedID("not-a-valid-gidx-id"), + errorMsg: "invalid id", + }, } for _, tt := range testCases { t.Run(tt.TestName, func(t *testing.T) { - resp, err := graphTestClient().LoadBalancerProviderDelete(ctx, prov.ID) + resp, err := graphTestClient().LoadBalancerProviderDelete(ctx, tt.Input) if tt.errorMsg != "" { require.Error(t, err) From 2e450e0d7641b0e45182bbe058a668f5fda2ed52 Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Tue, 26 Sep 2023 16:52:48 +0000 Subject: [PATCH 08/10] minor logging additions Signed-off-by: Matt Siwiec --- internal/graphapi/origin.resolvers.go | 6 +++--- internal/graphapi/pool.resolvers.go | 10 +++++----- internal/graphapi/port.resolvers.go | 6 ++++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/internal/graphapi/origin.resolvers.go b/internal/graphapi/origin.resolvers.go index e4a77a005..e1a36c39f 100644 --- a/internal/graphapi/origin.resolvers.go +++ b/internal/graphapi/origin.resolvers.go @@ -17,12 +17,12 @@ import ( func (r *mutationResolver) LoadBalancerOriginCreate(ctx context.Context, input generated.CreateLoadBalancerOriginInput) (*LoadBalancerOriginCreatePayload, error) { logger := r.logger.With("poolID", input.PoolID) - if err := permissions.CheckAccess(ctx, input.PoolID, actionLoadBalancerPoolUpdate); err != nil { + // check gidx format + if _, err := gidx.Parse(input.PoolID.String()); err != nil { return nil, err } - // check gidx format - if _, err := gidx.Parse(input.PoolID.String()); err != nil { + if err := permissions.CheckAccess(ctx, input.PoolID, actionLoadBalancerPoolUpdate); err != nil { return nil, err } diff --git a/internal/graphapi/pool.resolvers.go b/internal/graphapi/pool.resolvers.go index f6c08add2..5373db0c9 100644 --- a/internal/graphapi/pool.resolvers.go +++ b/internal/graphapi/pool.resolvers.go @@ -18,6 +18,8 @@ import ( // LoadBalancerPoolCreate is the resolver for the LoadBalancerPoolCreate field. func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input generated.CreateLoadBalancerPoolInput) (*LoadBalancerPoolCreatePayload, error) { + logger := r.logger.With("ownerID", input.OwnerID) + // check gidx owner format if _, err := gidx.Parse(input.OwnerID.String()); err != nil { return nil, err @@ -33,7 +35,7 @@ func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input gen return nil, err } - r.logger.Errorw("failed to create loadbalancer pool", "error", err) + logger.Errorw("failed to create loadbalancer pool", "error", err) return nil, ErrInternalServerError } @@ -42,7 +44,7 @@ func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input gen // LoadBalancerPoolUpdate is the resolver for the LoadBalancerPoolUpdate field. func (r *mutationResolver) LoadBalancerPoolUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerPoolInput) (*LoadBalancerPoolUpdatePayload, error) { - logger := r.logger.With("loadbalancerPoolID", id.String()) + logger := r.logger.With("loadbalancerPoolID", id) // check gidx format if _, err := gidx.Parse(id.String()); err != nil { @@ -78,7 +80,7 @@ func (r *mutationResolver) LoadBalancerPoolUpdate(ctx context.Context, id gidx.P // LoadBalancerPoolDelete is the resolver for the loadBalancerPoolDelete field. func (r *mutationResolver) LoadBalancerPoolDelete(ctx context.Context, id gidx.PrefixedID) (*LoadBalancerPoolDeletePayload, error) { - logger := r.logger.With("loadbalancerPoolID", id.String()) + logger := r.logger.With("loadbalancerPoolID", id) // check gidx format if _, err := gidx.Parse(id.String()); err != nil { @@ -106,8 +108,6 @@ func (r *mutationResolver) LoadBalancerPoolDelete(ctx context.Context, id gidx.P defer tx.Rollback() - // todo: cleanup pool assigments - // cleanup origins associated with pool origins, err := tx.Origin.Query().Where(predicate.Origin(origin.PoolIDEQ(id))).All(ctx) if err != nil { diff --git a/internal/graphapi/port.resolvers.go b/internal/graphapi/port.resolvers.go index 6438261ad..022d6b46f 100644 --- a/internal/graphapi/port.resolvers.go +++ b/internal/graphapi/port.resolvers.go @@ -16,6 +16,8 @@ import ( // LoadBalancerPortCreate is the resolver for the loadBalancerPortCreate field. func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input generated.CreateLoadBalancerPortInput) (*LoadBalancerPortCreatePayload, error) { + logger := r.logger.With("loadbalancerID", input.LoadBalancerID, "loadbalancerPools", input.PoolIDs) + // check gidx lb id format if _, err := gidx.Parse(input.LoadBalancerID.String()); err != nil { return nil, err @@ -40,7 +42,7 @@ func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input gen case generated.IsValidationError(err): return nil, err default: - r.logger.Errorw("failed to create loadbalancer port", "error", err) + logger.Errorw("failed to create loadbalancer port", "error", err) return nil, ErrInternalServerError } } @@ -50,7 +52,7 @@ func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input gen // LoadBalancerPortUpdate is the resolver for the loadBalancerPortUpdate field. func (r *mutationResolver) LoadBalancerPortUpdate(ctx context.Context, id gidx.PrefixedID, input generated.UpdateLoadBalancerPortInput) (*LoadBalancerPortUpdatePayload, error) { - logger := r.logger.With("loadbalancerPortID", id.String()) + logger := r.logger.With("loadbalancerPortID", id) // check gidx format if _, err := gidx.Parse(id.String()); err != nil { From f820b2b7c857bca13c5a75d6245d8cb113f828f9 Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Wed, 27 Sep 2023 21:53:43 +0000 Subject: [PATCH 09/10] rollback error log Signed-off-by: Matt Siwiec --- internal/graphapi/loadbalancer.resolvers.go | 6 +++++- internal/graphapi/pool.resolvers.go | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/internal/graphapi/loadbalancer.resolvers.go b/internal/graphapi/loadbalancer.resolvers.go index 01d4a017f..760436aa4 100644 --- a/internal/graphapi/loadbalancer.resolvers.go +++ b/internal/graphapi/loadbalancer.resolvers.go @@ -99,7 +99,11 @@ func (r *mutationResolver) LoadBalancerDelete(ctx context.Context, id gidx.Prefi return nil, ErrInternalServerError } - defer tx.Rollback() + defer func() { + if err := tx.Rollback(); err != nil { + logger.Errorw("failed to rollback transaction", "error", err) + } + }() // cleanup ports associated with loadbalancer ports, err := tx.Port.Query().Where(predicate.Port(port.LoadBalancerIDEQ(id))).All(ctx) diff --git a/internal/graphapi/pool.resolvers.go b/internal/graphapi/pool.resolvers.go index 5373db0c9..08e96a158 100644 --- a/internal/graphapi/pool.resolvers.go +++ b/internal/graphapi/pool.resolvers.go @@ -106,7 +106,11 @@ func (r *mutationResolver) LoadBalancerPoolDelete(ctx context.Context, id gidx.P return nil, ErrInternalServerError } - defer tx.Rollback() + defer func() { + if err := tx.Rollback(); err != nil { + logger.Errorw("failed to rollback transaction", "error", err) + } + }() // cleanup origins associated with pool origins, err := tx.Origin.Query().Where(predicate.Origin(origin.PoolIDEQ(id))).All(ctx) From e239871f68c549494ccdaaa151c348356cd26fbc Mon Sep 17 00:00:00 2001 From: Matt Siwiec Date: Thu, 5 Oct 2023 23:24:24 +0000 Subject: [PATCH 10/10] last look Signed-off-by: Matt Siwiec --- internal/graphapi/loadbalancer.resolvers.go | 2 +- internal/graphapi/pool.resolvers.go | 7 +++++-- internal/graphapi/port.resolvers.go | 22 +++++++++++++++++---- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/internal/graphapi/loadbalancer.resolvers.go b/internal/graphapi/loadbalancer.resolvers.go index d7c67c0cc..7362ec994 100644 --- a/internal/graphapi/loadbalancer.resolvers.go +++ b/internal/graphapi/loadbalancer.resolvers.go @@ -126,7 +126,7 @@ func (r *mutationResolver) LoadBalancerDelete(ctx context.Context, id gidx.Prefi for _, p := range ports { if err = tx.Port.DeleteOne(p).Exec(ctx); err != nil { - logger.Errorw("failed to delete port", "port", p.ID, "error", err) + logger.Errorw("failed to delete port", "loadbalancerPortID", p.ID, "error", err) return nil, ErrInternalServerError } } diff --git a/internal/graphapi/pool.resolvers.go b/internal/graphapi/pool.resolvers.go index 3da5d6a98..6e9df7680 100644 --- a/internal/graphapi/pool.resolvers.go +++ b/internal/graphapi/pool.resolvers.go @@ -33,7 +33,8 @@ func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input gen ids, err := r.client.Port.Query().Where(port.HasLoadBalancerWith(loadbalancer.OwnerIDEQ(input.OwnerID))).Where(port.IDIn(input.PortIDs...)).IDs(ctx) if err != nil { - return nil, err + logger.Errorw("failed to query input ports", "error", err) + return nil, ErrInternalServerError } if len(ids) < len(input.PortIDs) { @@ -42,6 +43,7 @@ func (r *mutationResolver) LoadBalancerPoolCreate(ctx context.Context, input gen for _, portId := range input.PortIDs { if err := permissions.CheckAccess(ctx, portId, actionLoadBalancerGet); err != nil { + logger.Errorw("failed to check access", "error", err, "loadbalancerPortID", portId) return nil, err } } @@ -94,6 +96,7 @@ func (r *mutationResolver) LoadBalancerPoolUpdate(ctx context.Context, id gidx.P for _, portId := range input.AddPortIDs { if err := permissions.CheckAccess(ctx, portId, actionLoadBalancerGet); err != nil { + logger.Errorw("failed to check access", "error", err, "loadbalancerPortID", portId) return nil, err } } @@ -154,7 +157,7 @@ func (r *mutationResolver) LoadBalancerPoolDelete(ctx context.Context, id gidx.P for _, o := range origins { if err = tx.Origin.DeleteOne(o).Exec(ctx); err != nil { - logger.Errorw("failed to delete origin", "origin", o.ID, "error", err) + logger.Errorw("failed to delete origin", "loadbalancerOriginID", o.ID, "error", err) return nil, ErrInternalServerError } } diff --git a/internal/graphapi/port.resolvers.go b/internal/graphapi/port.resolvers.go index d3628cde8..e973aea36 100644 --- a/internal/graphapi/port.resolvers.go +++ b/internal/graphapi/port.resolvers.go @@ -37,12 +37,18 @@ func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input gen lb, err := r.client.LoadBalancer.Get(ctx, input.LoadBalancerID) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer", "error", err) + return nil, ErrInternalServerError } ids, err := r.client.Pool.Query().Where(pool.OwnerIDEQ(lb.OwnerID)).Where(pool.IDIn(input.PoolIDs...)).IDs(ctx) if err != nil { - return nil, err + logger.Errorw("failed to query input pools", "error", err) + return nil, ErrInternalServerError } if len(ids) < len(input.PoolIDs) { @@ -51,6 +57,7 @@ func (r *mutationResolver) LoadBalancerPortCreate(ctx context.Context, input gen for _, poolId := range input.PoolIDs { if err := permissions.CheckAccess(ctx, poolId, actionLoadBalancerPoolGet); err != nil { + logger.Errorw("failed to check access", "error", err, "loadbalancerPoolID", poolId) return nil, err } } @@ -96,12 +103,18 @@ func (r *mutationResolver) LoadBalancerPortUpdate(ctx context.Context, id gidx.P lb, err := r.client.LoadBalancer.Get(ctx, p.LoadBalancerID) if err != nil { - return nil, err + if generated.IsNotFound(err) { + return nil, err + } + + logger.Errorw("failed to get loadbalancer", "error", err) + return nil, ErrInternalServerError } ids, err := r.client.Pool.Query().Where(pool.OwnerIDEQ(lb.OwnerID)).Where(pool.IDIn(input.AddPoolIDs...)).IDs(ctx) if err != nil { - return nil, err + logger.Errorw("failed to query input pools", "error", err) + return nil, ErrInternalServerError } if len(ids) < len(input.AddPoolIDs) { @@ -110,6 +123,7 @@ func (r *mutationResolver) LoadBalancerPortUpdate(ctx context.Context, id gidx.P for _, poolId := range input.AddPoolIDs { if err := permissions.CheckAccess(ctx, poolId, actionLoadBalancerPoolGet); err != nil { + logger.Errorw("failed to check access", "error", err, "loadbalancerPoolID", poolId) return nil, err } }