diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0effb36 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +--- +version: 2 +updates: + - package-ecosystem: "gomod" + directory: "/" + schedule: + interval: "monthly" + labels: + - "area/dependencies" + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "monthly" + labels: + - "area/dependencies" diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml new file mode 100644 index 0000000..84c5cf9 --- /dev/null +++ b/.github/workflows/build-test.yaml @@ -0,0 +1,19 @@ +--- +name: "Build & Test" +on: # yamllint disable-line rule:truthy + push: + branches: + - "main" + pull_request: + branches: + - "*" +jobs: + unit: + name: "Unit" + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v3" + - uses: "actions/setup-go@v3" + with: + go-version: "~1.19" + - uses: "authzed/actions/go-test@main" diff --git a/.github/workflows/cla.yaml b/.github/workflows/cla.yaml new file mode 100644 index 0000000..cb29e48 --- /dev/null +++ b/.github/workflows/cla.yaml @@ -0,0 +1,20 @@ +--- +name: "CLA" +on: # yamllint disable-line rule:truthy + issue_comment: + types: + - "created" + pull_request_target: + types: + - "opened" + - "closed" + - "synchronize" +jobs: + cla: + name: "Check Signature" + runs-on: "ubuntu-latest" + steps: + - uses: "authzed/actions/cla-check@main" + with: + github_token: "${{ secrets.GITHUB_TOKEN }}" + cla_assistant_token: "${{ secrets.CLA_ASSISTANT_ACCESS_TOKEN }}" diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..70f699e --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,45 @@ +--- +name: "Lint" +on: # yamllint disable-line rule:truthy + push: + branches: + - "!dependabot/*" + - "main" + pull_request: + branches: ["*"] +jobs: + go-lint: + name: "Lint Go" + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v3" + - uses: "actions/setup-go@v3" + with: + go-version: "~1.19" + - uses: "authzed/actions/gofumpt@main" + - uses: "authzed/actions/go-generate@main" + - uses: "authzed/actions/golangci-lint@main" + + extra-lint: + name: "Lint YAML & Markdown" + runs-on: "ubuntu-latest" + steps: + - uses: "actions/checkout@v3" + - uses: "authzed/actions/yaml-lint@main" + - uses: "authzed/actions/markdown-lint@main" + +# TODO: enable when public +# codeql: +# name: "Analyze with CodeQL" +# runs-on: "ubuntu-latest" +# permissions: +# actions: "read" +# contents: "read" +# security-events: "write" +# strategy: +# fail-fast: false +# matrix: +# language: ["go"] +# steps: +# - uses: "actions/checkout@v3" +# - uses: "authzed/actions/codeql@main" diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..f0cf491 --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,38 @@ +--- +run: + timeout: "5m" +output: + sort-results: true +linters: + enable: + - "bidichk" + - "bodyclose" + - "deadcode" + - "errcheck" + - "errname" + - "errorlint" + - "gofumpt" + - "goimports" + - "goprintffuncname" + - "gosec" + - "gosimple" + - "govet" + - "ifshort" + - "importas" + - "ineffassign" + - "makezero" + - "prealloc" + - "predeclared" + - "promlinter" + - "revive" + - "rowserrcheck" + - "staticcheck" + - "structcheck" + - "stylecheck" + - "tenv" + - "typecheck" + - "unconvert" + - "unused" + - "varcheck" + - "wastedassign" + - "whitespace" diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..80875d4 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,3 @@ +--- +line-length: false +no-hard-tabs: false diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..9c1e7e3 --- /dev/null +++ b/.yamllint @@ -0,0 +1,10 @@ +# vim: ft=yaml +--- +yaml-files: + - "*.yaml" + - "*.yml" + - ".yamllint" +extends: "default" +rules: + quoted-strings: "enable" + line-length: "disable" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d97f89b..c29a524 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -85,3 +85,17 @@ go get github.com/org/newdependency@version ``` Continuous integration enforces that `go mod tidy` has been run. + +### Codegen and Linting + +To run all code generators: + +```sh +go generate ./... +``` + +To run all tooling, including linters: + +```sh +go generate -tags tools ./... +``` diff --git a/README.md b/README.md index 7d18128..a42c1bb 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Looking to contribute? See [CONTRIBUTING.md]. [Discord]: https://authzed.com/discord [CONTRIBUTING.md]: https://github.com/authzed/spicedb/blob/main/CONTRIBUTING.md -## Overview +## Overview ### Handlers @@ -70,7 +70,7 @@ func mainControlLoop(ctx context.Context) { ``` The `handler` package contains utilities for building, composing, and decorating handlers, and for building large state machines with them. -See the [docs]() for more details. +See the [docs](https://pkg.go.dev/github.com/authzed/controller-idioms/handler) for more details. Handlers take some inspiration from [statecharts](https://statecharts.dev/) to deal with the complexity of writing and maintaining controllers, while staying close to golang idioms. @@ -96,6 +96,7 @@ func (h *UseHandler) Handle(ctx context.Context) { `Handlers` are typically chained in a way that preserves the context between handlers, but not always. For example: + ```go var CtxExpensiveObject = typedctx.NewKey[ExpensiveComputation]() @@ -147,7 +148,7 @@ secrets, err := secretIndexer.ByIndex("my-index-name", "my-index-value") ### Controllers and Managers -The `manager` package provides an optional lightweight controller `Manager` abstraction (similar to kubernetes controller manager, or the manager from controller runtime). It also provides a simple `Controller` abstraction and some basic implementations. +The `manager` package provides an optional lightweight controller `Manager` abstraction (similar to kubernetes controller manager, or the manager from controller runtime). It also provides a simple `Controller` abstraction and some basic implementations. The rest of `controller-idioms` can be used without using these if you are already using another solution. @@ -190,7 +191,6 @@ The queue operations are: If calling these controls from a handler, it's important to `return` immediately so that the handler does not continue processing a key that the queue thinks has stopped. - ### Middleware Middleware can be injected between handlers with the `middleware` package. diff --git a/adopt/adopt_test.go b/adopt/adopt_test.go index 806352d..e8331ad 100644 --- a/adopt/adopt_test.go +++ b/adopt/adopt_test.go @@ -300,7 +300,7 @@ func TestSecretAdopterHandler(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - ctrls := &fake.FakeOperations{} + ctrls := &fake.FakeInterface{} indexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{IndexName: OwnerKeysFromMeta(OwnerAnnotationPrefix)}) IndexAddUnstructured(t, indexer, tt.secretsInIndex) @@ -377,7 +377,6 @@ func NewSecretAdoptionHandler(recorder record.EventRecorder, getFromCache func(c } func ExampleAdoptionHandler_Handle() { - } func ExpectEvents(t *testing.T, recorder *record.FakeRecorder, expected []string) { diff --git a/bootstrap/crds_test.go b/bootstrap/crds_test.go index e728260..153d48e 100644 --- a/bootstrap/crds_test.go +++ b/bootstrap/crds_test.go @@ -10,6 +10,6 @@ import ( var crdFS embed.FS func ExampleCRD() { - CRD(&rest.Config{}, crdFS, "example") + _ = CRD(&rest.Config{}, crdFS, "example") // Output: } diff --git a/bootstrap/example.yaml b/bootstrap/example.yaml index abe2a77..98ebaff 100644 --- a/bootstrap/example.yaml +++ b/bootstrap/example.yaml @@ -1,8 +1,9 @@ -apiVersion: v1 -kind: Secret +--- +apiVersion: "v1" +kind: "Secret" metadata: - namespace: test - name: example -type: Opaque + namespace: "test" + name: "example" +type: "Opaque" data: - required: data + required: "data" diff --git a/bootstrap/example/crd.yaml b/bootstrap/example/crd.yaml index 8c2f1f5..2224b0b 100644 --- a/bootstrap/example/crd.yaml +++ b/bootstrap/example/crd.yaml @@ -1,16 +1,17 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition +--- +apiVersion: "apiextensions.k8s.io/v1" +kind: "CustomResourceDefinition" metadata: - name: mytype.example.com + name: "mytype.example.com" spec: - group: example.com + group: "example.com" names: - kind: MyType - listKind: MyTypeList - plural: mytypes - singular: mytype - scope: Namespaced + kind: "MyType" + listKind: "MyTypeList" + plural: "mytypes" + singular: "mytype" + scope: "Namespaced" versions: - - name: v1 + - name: "v1" served: true storage: true diff --git a/bootstrap/resource_test.go b/bootstrap/resource_test.go index 44892a9..9b93f03 100644 --- a/bootstrap/resource_test.go +++ b/bootstrap/resource_test.go @@ -21,13 +21,18 @@ func ExampleResourceFromFile() { secretGVR := corev1.SchemeGroupVersion.WithResource("secrets") scheme := runtime.NewScheme() - corev1.AddToScheme(scheme) + if err := corev1.AddToScheme(scheme); err != nil { + panic(err) + } scheme.AddKnownTypes(corev1.SchemeGroupVersion, &corev1.Secret{}) client := secretApplyPatchHandlingFakeClient(scheme) // create the object from the file // the example is a secret, but it could be any built-in or CRD-defined type - ResourceFromFile[*corev1.Secret](ctx, "bootstrapped-secret", secretGVR, client, "./example.yaml", 0) + _, err := ResourceFromFile[*corev1.Secret](ctx, "bootstrapped-secret", secretGVR, client, "./example.yaml", 0) + if err != nil { + panic(err) + } for { secret, err := client.Resource(secretGVR).Namespace("test").Get(ctx, "example", metav1.GetOptions{}) diff --git a/client/rest.go b/client/rest.go new file mode 100644 index 0000000..6bbcd91 --- /dev/null +++ b/client/rest.go @@ -0,0 +1,8 @@ +package client + +import "k8s.io/client-go/rest" + +func DisableClientSideRateLimiting(restConfig *rest.Config) { + restConfig.Burst = 2000 + restConfig.QPS = -1 +} diff --git a/component/ensure_component_test.go b/component/ensure_component_test.go index 72a1600..8eb9d6b 100644 --- a/component/ensure_component_test.go +++ b/component/ensure_component_test.go @@ -79,20 +79,23 @@ func TestEnsureServiceHandler(t *testing.T) { }, Annotations: map[string]string{ hashKey: "n5d8h56h6dhc7h96h8h545h96q", - }}}, + }, + }}, }, }, { name: "deletes extra services if a matching service exists", - existingServices: []runtime.Object{&corev1.Service{ObjectMeta: metav1.ObjectMeta{ - Name: "test", - Namespace: "test", - Labels: map[string]string{ - "example.com/component": "the-main-service-component", + existingServices: []runtime.Object{&corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test", + Labels: map[string]string{ + "example.com/component": "the-main-service-component", + }, + Annotations: map[string]string{ + hashKey: "n5d8h56h6dhc7h96h8h545h96q", + }, }, - Annotations: map[string]string{ - hashKey: "n5d8h56h6dhc7h96h8h545h96q", - }}, }, &corev1.Service{ObjectMeta: metav1.ObjectMeta{ Name: "extra", Namespace: "test", @@ -108,7 +111,7 @@ func TestEnsureServiceHandler(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - ctrls := &fake.FakeOperations{} + ctrls := &fake.FakeInterface{} applyCalled := false deleteCalled := false diff --git a/go.mod b/go.mod index 4fc735b..0ab9468 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/cespare/xxhash/v2 v2.1.2 github.com/davecgh/go-spew v1.1.1 github.com/fsnotify/fsnotify v1.5.4 + github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 github.com/prometheus/client_golang v1.13.0 github.com/stretchr/testify v1.8.0 golang.org/x/exp v0.0.0-20220823124025-807a23277127 @@ -19,6 +20,7 @@ require ( k8s.io/controller-manager v0.25.0 k8s.io/klog/v2 v2.70.1 k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 + mvdan.cc/gofumpt v0.3.1 sigs.k8s.io/controller-runtime v0.12.3 ) @@ -80,12 +82,14 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.19.1 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + golang.org/x/tools v0.1.12 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect google.golang.org/grpc v1.47.0 // indirect diff --git a/go.sum b/go.sum index 6301cd6..5baf362 100644 --- a/go.sum +++ b/go.sum @@ -95,6 +95,7 @@ github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQL github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ= github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.3+incompatible h1:7ZaBxOI7TMoYBfyA3cQHErNNyAWIKUMIwqxEtgHOs5c= +github.com/frankban/quicktest v1.14.2 h1:SPb1KFFmM+ybpEjPUhCCkZOM5xlovT5UbrMvWnXyBns= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -224,6 +225,7 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -235,6 +237,8 @@ github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g= +github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -246,12 +250,12 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A= 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= @@ -286,7 +290,9 @@ github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5 github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -410,6 +416,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -575,6 +583,8 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -677,8 +687,9 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= @@ -726,6 +737,8 @@ k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkI k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73 h1:H9TCJUUx+2VA0ZiD9lvtaX8fthFsMoD+Izn93E/hm8U= k8s.io/utils v0.0.0-20220823124924-e9cbc92d1a73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +mvdan.cc/gofumpt v0.3.1 h1:avhhrOmv0IuvQVK7fvwV91oFSGAk5/6Po8GXTzICeu8= +mvdan.cc/gofumpt v0.3.1/go.mod h1:w3ymliuxvzVx8DAutBnVyDqYb1Niy/yCJt/lk821YCE= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/handler/parallel_test.go b/handler/parallel_test.go index 46d77fa..816ae47 100644 --- a/handler/parallel_test.go +++ b/handler/parallel_test.go @@ -1,18 +1,27 @@ package handler -import "context" +import ( + "context" + "time" +) func ExampleParallel() { ctx, cancel := context.WithCancel(context.Background()) defer cancel() + // slow down the first stage to get a deterministic output + slowFirstStage := func(next ...Handler) Handler { + time.Sleep(5 * time.Millisecond) + return firstStageBuilder(next...) + } + // These handlers run in parallel, so their contexts are independent // i.e. FirstStage.next and SecondStage.next are both NoopHandlers // Any work that is done that needs to be used later on should use // typedctx.Boxed contexts so that the parallel steps can "fill in" // a predefined space. Parallel( - firstStageBuilder, + slowFirstStage, secondStageBuilder, ).Handler("firstAndSecond").Handle(ctx) diff --git a/manager/controller_test.go b/manager/controller_test.go index 5d68735..ffd34e6 100644 --- a/manager/controller_test.go +++ b/manager/controller_test.go @@ -34,6 +34,6 @@ func ExampleNewOwnedResourceController() { mgr := NewManager(ctrlmanageropts.RecommendedDebuggingOptions().DebuggingConfiguration, ":", broadcaster, eventSink) ctx, cancel := context.WithTimeout(context.Background(), 2*time.Millisecond) defer cancel() - mgr.Start(ctx, controller) + _ = mgr.Start(ctx, controller) // Output: } diff --git a/queue/controls.go b/queue/controls.go index fc5069c..071a86b 100644 --- a/queue/controls.go +++ b/queue/controls.go @@ -68,7 +68,7 @@ func NewOperations(done func(), requeueAfter func(time.Duration)) *Operations { // Interface is the standard queue control interface // -//counterfeiter:generate -o ./fake . Interface +//counterfeiter:generate -o ./fake/zz_generated.go . Interface type Interface interface { Done() RequeueAfter(duration time.Duration) diff --git a/queue/controls_test.go b/queue/controls_test.go index 632fdf7..dd12c5f 100644 --- a/queue/controls_test.go +++ b/queue/controls_test.go @@ -31,7 +31,6 @@ func ExampleNewOperations() { handler.NewHandlerFromFunc(func(ctx context.Context) { // do some work operations.Done() - return }, "example").Handle(ctx) fmt.Println(queue.Len()) @@ -64,7 +63,6 @@ func ExampleNewQueueOperationsCtx() { handler.NewHandlerFromFunc(func(ctx context.Context) { // do some work CtxQueue.Done() - return }, "example").Handle(ctx) fmt.Println(queue.Len()) diff --git a/queue/fake/fake_operations.go b/queue/fake/fake_operations.go deleted file mode 100644 index fb49609..0000000 --- a/queue/fake/fake_operations.go +++ /dev/null @@ -1,215 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fake - -import ( - "sync" - "time" - - "github.com/authzed/controller-idioms/queue" -) - -type FakeOperations struct { - DoneStub func() - doneMutex sync.RWMutex - doneArgsForCall []struct { - } - RequeueStub func() - requeueMutex sync.RWMutex - requeueArgsForCall []struct { - } - RequeueAPIErrStub func(error) - requeueAPIErrMutex sync.RWMutex - requeueAPIErrArgsForCall []struct { - arg1 error - } - RequeueAfterStub func(time.Duration) - requeueAfterMutex sync.RWMutex - requeueAfterArgsForCall []struct { - arg1 time.Duration - } - RequeueErrStub func(error) - requeueErrMutex sync.RWMutex - requeueErrArgsForCall []struct { - arg1 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *FakeOperations) Done() { - fake.doneMutex.Lock() - fake.doneArgsForCall = append(fake.doneArgsForCall, struct { - }{}) - stub := fake.DoneStub - fake.recordInvocation("Done", []interface{}{}) - fake.doneMutex.Unlock() - if stub != nil { - fake.DoneStub() - } -} - -func (fake *FakeOperations) DoneCallCount() int { - fake.doneMutex.RLock() - defer fake.doneMutex.RUnlock() - return len(fake.doneArgsForCall) -} - -func (fake *FakeOperations) DoneCalls(stub func()) { - fake.doneMutex.Lock() - defer fake.doneMutex.Unlock() - fake.DoneStub = stub -} - -func (fake *FakeOperations) Requeue() { - fake.requeueMutex.Lock() - fake.requeueArgsForCall = append(fake.requeueArgsForCall, struct { - }{}) - stub := fake.RequeueStub - fake.recordInvocation("Requeue", []interface{}{}) - fake.requeueMutex.Unlock() - if stub != nil { - fake.RequeueStub() - } -} - -func (fake *FakeOperations) RequeueCallCount() int { - fake.requeueMutex.RLock() - defer fake.requeueMutex.RUnlock() - return len(fake.requeueArgsForCall) -} - -func (fake *FakeOperations) RequeueCalls(stub func()) { - fake.requeueMutex.Lock() - defer fake.requeueMutex.Unlock() - fake.RequeueStub = stub -} - -func (fake *FakeOperations) RequeueAPIErr(arg1 error) { - fake.requeueAPIErrMutex.Lock() - fake.requeueAPIErrArgsForCall = append(fake.requeueAPIErrArgsForCall, struct { - arg1 error - }{arg1}) - stub := fake.RequeueAPIErrStub - fake.recordInvocation("RequeueAPIErr", []interface{}{arg1}) - fake.requeueAPIErrMutex.Unlock() - if stub != nil { - fake.RequeueAPIErrStub(arg1) - } -} - -func (fake *FakeOperations) RequeueAPIErrCallCount() int { - fake.requeueAPIErrMutex.RLock() - defer fake.requeueAPIErrMutex.RUnlock() - return len(fake.requeueAPIErrArgsForCall) -} - -func (fake *FakeOperations) RequeueAPIErrCalls(stub func(error)) { - fake.requeueAPIErrMutex.Lock() - defer fake.requeueAPIErrMutex.Unlock() - fake.RequeueAPIErrStub = stub -} - -func (fake *FakeOperations) RequeueAPIErrArgsForCall(i int) error { - fake.requeueAPIErrMutex.RLock() - defer fake.requeueAPIErrMutex.RUnlock() - argsForCall := fake.requeueAPIErrArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeOperations) RequeueAfter(arg1 time.Duration) { - fake.requeueAfterMutex.Lock() - fake.requeueAfterArgsForCall = append(fake.requeueAfterArgsForCall, struct { - arg1 time.Duration - }{arg1}) - stub := fake.RequeueAfterStub - fake.recordInvocation("RequeueAfter", []interface{}{arg1}) - fake.requeueAfterMutex.Unlock() - if stub != nil { - fake.RequeueAfterStub(arg1) - } -} - -func (fake *FakeOperations) RequeueAfterCallCount() int { - fake.requeueAfterMutex.RLock() - defer fake.requeueAfterMutex.RUnlock() - return len(fake.requeueAfterArgsForCall) -} - -func (fake *FakeOperations) RequeueAfterCalls(stub func(time.Duration)) { - fake.requeueAfterMutex.Lock() - defer fake.requeueAfterMutex.Unlock() - fake.RequeueAfterStub = stub -} - -func (fake *FakeOperations) RequeueAfterArgsForCall(i int) time.Duration { - fake.requeueAfterMutex.RLock() - defer fake.requeueAfterMutex.RUnlock() - argsForCall := fake.requeueAfterArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeOperations) RequeueErr(arg1 error) { - fake.requeueErrMutex.Lock() - fake.requeueErrArgsForCall = append(fake.requeueErrArgsForCall, struct { - arg1 error - }{arg1}) - stub := fake.RequeueErrStub - fake.recordInvocation("RequeueErr", []interface{}{arg1}) - fake.requeueErrMutex.Unlock() - if stub != nil { - fake.RequeueErrStub(arg1) - } -} - -func (fake *FakeOperations) RequeueErrCallCount() int { - fake.requeueErrMutex.RLock() - defer fake.requeueErrMutex.RUnlock() - return len(fake.requeueErrArgsForCall) -} - -func (fake *FakeOperations) RequeueErrCalls(stub func(error)) { - fake.requeueErrMutex.Lock() - defer fake.requeueErrMutex.Unlock() - fake.RequeueErrStub = stub -} - -func (fake *FakeOperations) RequeueErrArgsForCall(i int) error { - fake.requeueErrMutex.RLock() - defer fake.requeueErrMutex.RUnlock() - argsForCall := fake.requeueErrArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *FakeOperations) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.doneMutex.RLock() - defer fake.doneMutex.RUnlock() - fake.requeueMutex.RLock() - defer fake.requeueMutex.RUnlock() - fake.requeueAPIErrMutex.RLock() - defer fake.requeueAPIErrMutex.RUnlock() - fake.requeueAfterMutex.RLock() - defer fake.requeueAfterMutex.RUnlock() - fake.requeueErrMutex.RLock() - defer fake.requeueErrMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *FakeOperations) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ queue.Interface = new(FakeOperations) diff --git a/queue/fake/fake_interface.go b/queue/fake/zz_generated.go similarity index 100% rename from queue/fake/fake_interface.go rename to queue/fake/zz_generated.go diff --git a/static/controller_test.go b/static/controller_test.go index a62d98e..87caf5d 100644 --- a/static/controller_test.go +++ b/static/controller_test.go @@ -21,7 +21,9 @@ func ExampleController() { secretGVR := corev1.SchemeGroupVersion.WithResource("secrets") scheme := runtime.NewScheme() - corev1.AddToScheme(scheme) + if err := corev1.AddToScheme(scheme); err != nil { + panic(err) + } scheme.AddKnownTypes(corev1.SchemeGroupVersion, &corev1.Secret{}) client := secretApplyPatchHandlingFakeClient(scheme) diff --git a/static/example.yaml b/static/example.yaml index abe2a77..98ebaff 100644 --- a/static/example.yaml +++ b/static/example.yaml @@ -1,8 +1,9 @@ -apiVersion: v1 -kind: Secret +--- +apiVersion: "v1" +kind: "Secret" metadata: - namespace: test - name: example -type: Opaque + namespace: "test" + name: "example" +type: "Opaque" data: - required: data + required: "data" diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..35695e7 --- /dev/null +++ b/tools.go @@ -0,0 +1,11 @@ +//go:build tools +// +build tools + +package tools + +//go:generate go run mvdan.cc/gofumpt -l -w . + +import ( + _ "github.com/maxbrunsfeld/counterfeiter/v6" + _ "mvdan.cc/gofumpt" +) diff --git a/typed/registry_test.go b/typed/registry_test.go index 0214874..015fbaf 100644 --- a/typed/registry_test.go +++ b/typed/registry_test.go @@ -24,7 +24,9 @@ func ExampleRegistry() { }, }} scheme := runtime.NewScheme() - corev1.AddToScheme(scheme) + if err := corev1.AddToScheme(scheme); err != nil { + panic(err) + } client := fake.NewSimpleDynamicClient(scheme, &secret) registry := NewRegistry() @@ -67,7 +69,9 @@ func ExampleListerFor() { }, }} scheme := runtime.NewScheme() - corev1.AddToScheme(scheme) + if err := corev1.AddToScheme(scheme); err != nil { + panic(err) + } client := fake.NewSimpleDynamicClient(scheme, &secret) registry := NewRegistry() @@ -105,7 +109,9 @@ func ExampleIndexerFor() { }, }} scheme := runtime.NewScheme() - corev1.AddToScheme(scheme) + if err := corev1.AddToScheme(scheme); err != nil { + panic(err) + } client := fake.NewSimpleDynamicClient(scheme, &secret) registry := NewRegistry() @@ -123,11 +129,13 @@ func ExampleIndexerFor() { // add an index that indexes all objects with a constant value const indexName = "ExampleIndex" const constantIndexValue = "indexVal" - informerFactory.ForResource(secretGVR).Informer().AddIndexers(map[string]cache.IndexFunc{ + if err := informerFactory.ForResource(secretGVR).Informer().AddIndexers(map[string]cache.IndexFunc{ indexName: func(obj interface{}) ([]string, error) { return []string{constantIndexValue}, nil }, - }) + }); err != nil { + panic(err) + } informerFactory.Start(ctx.Done()) informerFactory.WaitForCacheSync(ctx.Done()) diff --git a/typedctx/context_test.go b/typedctx/context_test.go index 36d52ec..332b823 100644 --- a/typedctx/context_test.go +++ b/typedctx/context_test.go @@ -11,7 +11,7 @@ func ExampleKey() { type ExpensiveComputation struct { result string } - var CtxExpensiveObject = NewKey[*ExpensiveComputation]() + CtxExpensiveObject := NewKey[*ExpensiveComputation]() useHandler := handler.NewHandlerFromFunc(func(ctx context.Context) { // fetch the computed value after the computation @@ -22,7 +22,6 @@ func ExampleKey() { computeHandler := handler.NewHandlerFromFunc(func(ctx context.Context) { myComputedExpensiveObject := ExpensiveComputation{result: "computed"} ctx = CtxExpensiveObject.WithValue(ctx, &myComputedExpensiveObject) - useHandler.Handle(ctx) }, "compute") @@ -35,7 +34,7 @@ func ExampleWithDefault() { type ExpensiveComputation struct { result string } - var CtxExpensiveObject = WithDefault[*ExpensiveComputation](&ExpensiveComputation{result: "pending"}) + CtxExpensiveObject := WithDefault[*ExpensiveComputation](&ExpensiveComputation{result: "pending"}) useHandler := handler.NewHandlerFromFunc(func(ctx context.Context) { // fetch the computed value after the computation @@ -63,12 +62,12 @@ func ExampleBoxed() { type ExpensiveComputation struct { result string } - var CtxExpensiveObject = Boxed[*ExpensiveComputation](nil) + CtxExpensiveObject := Boxed[*ExpensiveComputation](nil) // the compute handler performs some computation that we wish to re-use computeHandler := handler.NewHandlerFromFunc(func(ctx context.Context) { myComputedExpensiveObject := ExpensiveComputation{result: "computed"} - ctx = CtxExpensiveObject.WithValue(ctx, &myComputedExpensiveObject) + CtxExpensiveObject.WithValue(ctx, &myComputedExpensiveObject) }, "compute") decorateHandler := handler.NewHandlerFromFunc(func(ctx context.Context) {